Files
ocs/mss/pps/src/main/mfunc.c
2025-03-03 11:01:26 +08:00

6431 lines
179 KiB
C

#include "../include/includes.h"
#include "../include/ramdata.h"
#include "../include/message.h"
#include "../include/ppsm.h"
#include "../include/crypt.h"
#include "../include/ppsoid.h"
#include "../include/cdrme.h"
#include "../include/param.h"
//#include "../include/mfunc.h"
#include "../include/plat_inc.h"
#include "../../../../plat/scf/src/include/scfmsg.h"
/*------------------------------------------------*/
extern _state_machine *smshm_ptr;
extern _tariff_private *blf_shmp;
extern _ram_data *ramshm_ptr;
extern _debug_info *debug_shmp;
extern int csta_now_instance,csta_old_instance;
extern int logMsgFlag;
extern struct timeval tvnow;
/*------------------------------------------------*/
extern PPSParamStruct ppsParam;
/*------------------------------------------------*/
extern int FindPPSSubsStoreIndex();
extern int AccountLatchFlagCheck();
extern int GetRechargeCardValidTime();
extern int GetRechargeCardFaceValue();
extern int IsPSTNMaitenance();
extern int IsVMSDeposit();
extern int IsCallingCardNumber(char *number);
//extern int des();
extern void SendAccountRealSync_2(_account_info *accountInfo, double balance, double promotion, int ocode);
extern void increPoolChildCharged(_account_info *ptr,double charged);
extern void increPoolChildSMS(_account_info *ptr);
extern void increPoolChildCalls(_account_info *ptr);
extern BOOL isPromotionCanBeUsedAtThisPoint(_state_data *shmp);
extern float BillingFormula(_state_data *shmp,_bill_tariff *ptar,int startTime);
extern float TimeToCharge(_state_data *shmp,_bill_tariff *ptar, int duration,int begin_time, int init_bill);
extern double GetBalanceWithPromotionControl(_state_data *stateProc,_account_info *ptr);
extern float caculateMiniCharge(_state_data *shmp,_bill_tariff *ptar);
extern int preLeftTime(_state_data *shmp,float balance,_bill_tariff *ptar);
extern void PPSSendUserSMSNotification(int head, int tail,char *msgSend);
extern u_char getCurrentTier(_state_data *shmp,_bill_tariff *ptar);
extern void ChangeTariffToPoolCallTariff(_state_data *shmp,_bill_tariff *ptar);
extern float getCurrentFee(_state_data *shmp);
extern int isPoolChildReachSMSLimit(_state_data *shmp);
extern char *sendPPSNotificationMessage(int head, int tail, int sms_id);
extern u_char *getSmsSentenceNative(SMS_SENTENCE id,u8 languageType);
extern BYTE ChangeUserCategory(BYTE *msisdn,BYTE type);
extern int subscribe_bundle_plan_send_used_up_info(char *caller_number, SMS_SENTENCE id);
extern void pps_print_error(u_char logMsisdnFlag,const char *fmt, ...);
extern int reportGprsCDRIncrement(int duration, float charge, long gprsVolume);
float GetAccountBalance(int head, int tail);
int isPoolChildReachFeeLimit(_account_info *ptr);
/*------------------------------------------------*/
int GetMOTariffData(_state_data *shmp,_bill_tariff *ptar, char *call_no, int zone_id)
{
int len=0,maxlen=0,msisdn_len;
int loop,index=-1;
_bill_tariff *ptr;
PutLogFunID("GetMOTariffData");
msisdn_len = strlen(call_no);
if (zone_id >= MAX_ZONE_NUM || zone_id <0) zone_id = 0;
if(ppsParam.serviceControl.cos_group_flag)// only use one type of tariff table in specify system
{// search by tree in this kind of tariff table
if(zone_id>=MAX_ZONE_NUM_NEW)
{
DebugMsg(debugmib.display.asciiOut, "search prefix failed: zone id = %d, called_no=%s",
zone_id,call_no);
return 0;
}
index = pps_get_charge_prefix(zone_id, call_no);// search tariff table by prefix of called number
if(index>=0)
{
ptr = &blf_shmp->bill_tariff[index/BILLING_BASE_NUM][index%BILLING_BASE_NUM];
memcpy(ptar,ptr,sizeof(_bill_tariff));// cpy content of tariff table
if(shmp != NULL)// save address of table
{
shmp->process_info.tariffMoReadOnly = &blf_shmp->bill_tariff[index/BILLING_BASE_NUM][index%BILLING_BASE_NUM];
}
return 1;
}
else
return 0;
/*
for(loop0=0;loop0<COS_GROUP_NUM;loop++)
{
for(loop=0;loop<BILLING_BASE_NUM;loop++)
{
ptr = &blf_shmp->bill_tariff[zone_id][loop];
len = strlen(ptr->bill_id);
if(len == 0) break;
if(len>maxlen && len<=msisdn_len)
{
if(!strncasecmp(call_no,ptr->bill_id,len))
{
maxlen = len;
index = loop;
}
}
}
}
*/
}
else
{// for this kind of tariff table, has 16 sub items; each has 1024 records
for(loop=0;loop<BILLING_BASE_NUM;loop++)// match prefix one by one
{
ptr = &blf_shmp->bill_tariff[zone_id][loop];
len = strlen(ptr->bill_id);
if(len == 0) break;
if(len>maxlen && len<=msisdn_len)
{
if(!strncasecmp(call_no,ptr->bill_id,len))
{
maxlen = len;
index = loop;
}
}
}
}
if(index>=0)
{
ptr = &blf_shmp->bill_tariff[zone_id][index];
memcpy(ptar,ptr,sizeof(_bill_tariff));
if(shmp != NULL)
{
shmp->process_info.tariffMoReadOnly = &blf_shmp->bill_tariff[zone_id][index];
}
return 1;
}
return FALSE;
}
int
IsNormalAccount(_account_info *ptr)
{
if(ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
return TRUE;
}
return FALSE;
}
int GetAccountFavoriteNumberCounter(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
if(ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
return shmp->prepaid_info[ptr->head][ptr->tail].favorite_numbers;
}else
{
return -1;
}
}
int StoreAccountFavoriteNumber(_account_info *ptr,char *msisdn,int index)
{
int i,len;
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("StoreAccountFavoriteNumber");
if(index>0 && index<=MAX_FAVORITE_NUMBERS)
{
len = strlen(msisdn);
shmp->prepaid_info[ptr->head][ptr->tail].favorite_number[index-1][MAX_MSISDN_BLEN-1] = len;
if(len%2==1)
len ++;
AsciiToBcd(shmp->prepaid_info[ptr->head][ptr->tail].favorite_number[index-1],msisdn,len);
return index;
}
if(ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
for(i=0;i<MAX_FAVORITE_NUMBERS;i++)
{
if(shmp->prepaid_info[ptr->head][ptr->tail].favorite_number[i][MAX_MSISDN_BLEN-1]<3)
{
len = strlen(msisdn);
shmp->prepaid_info[ptr->head][ptr->tail].favorite_number[i][MAX_MSISDN_BLEN-1] = len;
if(len%2==1)
len ++;
AsciiToBcd(shmp->prepaid_info[ptr->head][ptr->tail].favorite_number[i],msisdn,len);
shmp->prepaid_info[ptr->head][ptr->tail].favorite_numbers++;
if(shmp->prepaid_info[ptr->head][ptr->tail].favorite_numbers>MAX_FAVORITE_NUMBERS)
shmp->prepaid_info[ptr->head][ptr->tail].favorite_numbers=MAX_FAVORITE_NUMBERS;
return (i+1);
}
}
return (i+1);
}else
{
return -1;
}
}
int GetAccountFavoriteNumber(_account_info *ptr,char *msisdn,u_char index)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
int len;
PutLogFunID("GetAccountFavoriteNumber");
if(index<=MAX_FAVORITE_NUMBERS && index>0)
{
len = shmp->prepaid_info[ptr->head][ptr->tail].favorite_number[index-1][MAX_MSISDN_BLEN-1];
if(len<3 || len>16)
{
return 0;
}
memcpy(msisdn,
shmp->prepaid_info[ptr->head][ptr->tail].favorite_number[index-1],
MAX_MSISDN_BLEN);
return index;
}
return 0;
}
int
GetAccountPos(_account_info *ptr)
{
int len=0,store_index;
char msisdn[32];
PutLogFunID("GetAccountPos");
len = strlen((char *)ptr->number);
strcpy(msisdn, (char *)ptr->number);
if(len<MIN_MSISDN_ALEN || len>MAX_MSISDN_ALEN)
{
ptr->head = MSISDN_HEAD_NUM + 1;
ptr->tail = UNIT_STORE_ACCOUNT + 1;
return FALSE;
}
store_index = FindPPSSubsStoreIndex(atoll((char *)ptr->number));
if(store_index<0)
{
ptr->head = MSISDN_HEAD_NUM + 1;
ptr->tail = UNIT_STORE_ACCOUNT + 1;
return FALSE;
}
ptr->head = store_index / UNIT_STORE_ACCOUNT;
ptr->tail = store_index % UNIT_STORE_ACCOUNT;
return TRUE;
}
int
GetUserInstance(long long head,int *instance)
{
int loop;
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetUserInstance");
for(loop=0;loop<MSISDN_HEAD_NUM;loop++)
{
if(head == shmp->msisdn_head[loop])
{
*instance = loop ;
return 1;
}
}
return 0;
}
int
GetUserPos(int *head,long long head1)
{
int loop;
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetUserPos");
for(loop=0;loop<MSISDN_HEAD_NUM;loop++)
{
if(shmp->msisdn_head[loop] !=0)
if(head1 == shmp->msisdn_head[loop])
{
*head = loop;
return 1;
}
}
for(loop=0;loop<MSISDN_HEAD_NUM;loop++)
{
if(shmp->msisdn_head[loop] == 0)
{
*head = loop;
return 2;
}
}
return 0;
}
float
GetBalance(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetBalance");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT){
if(shmp->prepaid_info[ptr->head][ptr->tail].balance>=ppsParam.serviceControl.maxBalance)
shmp->prepaid_info[ptr->head][ptr->tail].status = T_SUSPEND;
if(shmp->prepaid_info[ptr->head][ptr->tail].msisdn[MAX_MSISDN_BLEN-1]<=2)
return 0;
return (shmp->prepaid_info[ptr->head][ptr->tail].balance +
shmp->prepaid_info[ptr->head][ptr->tail].promo_balance);
}
return 0;
}
long
GetExpiration(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetExpiration");
return (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT) ?
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date
: (tvnow.tv_sec+1);
}
long
GetIncomingExpiration(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetIncomingExpiration");
return (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT) ?
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date
: (tvnow.tv_sec+1);
}
int
GetOverdraft(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetOverdraft");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT) {
return shmp->prepaid_info[ptr->head][ptr->tail].overdraft;
}
return 0;
}
int IsPromotionExpired(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("IsPromotionExpired");
if(ptr == NULL) return 0;
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
if(shmp->prepaid_info[ptr->head][ptr->tail].promo_date > tvnow.tv_sec)
return 0;
}
return 1;
}
int
GetCMBTimes(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetCMBTimes");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT) {
return shmp->prepaid_info[ptr->head][ptr->tail].callMeBackRequestTimes;
}
return 0;
}
int
UpdateCMBTimes(_account_info *ptr,int times)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateCMBTimes");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
shmp->prepaid_info[ptr->head][ptr->tail].callMeBackRequestTimes += times;
SendAccountRealSync_2(ptr,0.0,0.0,OMC_OCODE_EDIT);
return 1;
}
return -1;
}
int
resetCMBTimes(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("resetCMBTimes");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
shmp->prepaid_info[ptr->head][ptr->tail].callMeBackRequestTimes = 0;
return 1;
}
return -1;
}
void UpdateBalanceForRecharge(_account_info *ptr, int charge)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateBalanceForRecharge");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
shmp->prepaid_info[ptr->head][ptr->tail].balance =
shmp->prepaid_info[ptr->head][ptr->tail].balance + charge;
if(shmp->prepaid_info[ptr->head][ptr->tail].balance >= 0)
shmp->prepaid_info[ptr->head][ptr->tail].overdraft = 0;
/* clear overdraft for each recharge */
}
}
void UpdateBalance(_state_data *stateProc,_account_info *ptr, float charge,CHARGED_FEE *chargeFee)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
u_char cos_id;
COSTable *cosTableItem;
double promo_balance,balance;
double chargedBalance = 0,chargedPromotion = 0;
PutLogFunID("UpdateBalance");
cos_id = ptr->cos_id%MaxCosTableItem;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
if(charge < 0
&& shmp->prepaid_info[ptr->head][ptr->tail].promo_balance > 0
&& isPromotionCanBeUsedAtThisPoint(stateProc))
{
promo_balance = shmp->prepaid_info[ptr->head][ptr->tail].promo_balance;
promo_balance = promo_balance + charge;
shmp->prepaid_info[ptr->head][ptr->tail].promo_balance = promo_balance;
chargedPromotion = charge;
}
else
{
balance = shmp->prepaid_info[ptr->head][ptr->tail].balance;
balance = balance + charge;
shmp->prepaid_info[ptr->head][ptr->tail].balance = balance;
chargedBalance = charge;
}
if(shmp->prepaid_info[ptr->head][ptr->tail].promo_balance<0)
{
chargedPromotion += shmp->prepaid_info[ptr->head][ptr->tail].promo_balance;
chargedBalance -= shmp->prepaid_info[ptr->head][ptr->tail].promo_balance;
shmp->prepaid_info[ptr->head][ptr->tail].balance +=
shmp->prepaid_info[ptr->head][ptr->tail].promo_balance;
shmp->prepaid_info[ptr->head][ptr->tail].promo_balance = 0;
}
if((shmp->prepaid_info[ptr->head][ptr->tail].balance +
shmp->prepaid_info[ptr->head][ptr->tail].overdraft)<=0)
{
if(cosTableItem->accountValidity[0].actionAfterBalanceDepleted)
{
if(shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date>
(tvnow.tv_sec + cosTableItem->accountValidity[0].validDaysChangeTo*24*3600))
{
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date =
tvnow.tv_sec + cosTableItem->accountValidity[0].validDaysChangeTo*24*3600;
}
if(shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date>
(tvnow.tv_sec + cosTableItem->accountValidity[0].validDaysChangeTo*24*3600))
{
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date =
tvnow.tv_sec + cosTableItem->accountValidity[0].validDaysChangeTo*24*3600;
}
}
}
chargeFee->balance = chargedBalance;
chargeFee->promotion = chargedPromotion;
increPoolChildCharged(ptr,-charge);
debugmib.display.totalCharge +=charge;
if(shmp->prepaid_info[ptr->head][ptr->tail].balance < 0)
{
if(shmp->prepaid_info[ptr->head][ptr->tail].overdraft <= 0)
{
shmp->prepaid_info[ptr->head][ptr->tail].balance = 0;
}
}
}
}
void UpdateAccountDefaultLanguageType(_account_info *ptr, u_char type)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateAccountDefaultLanguageType");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
shmp->prepaid_info[ptr->head][ptr->tail].language_type = type;
}
}
void UpdateAccountPIN(_account_info *ptr, char *pin)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateAccountPIN");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
memcpy(shmp->prepaid_info[ptr->head][ptr->tail].pin,pin,6);
}
}
int GetAccountPINByMsisdn(u_char *msisdn,u_char *pin)
{
_account_info info;
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetAccountPINByMsisdn");
memcpy(info.number,msisdn,strlen((char *)msisdn));
info.number[strlen((char *)msisdn)] = 0;
if(GetAccountPos(&info) == FALSE)
return -1;
if (info.head < MSISDN_HEAD_NUM && info.tail < UNIT_STORE_ACCOUNT)
{
memcpy(pin,shmp->prepaid_info[info.head][info.tail].pin,6);
}
return 1;
}
int CheckPINValidity(_account_info *ptr, char *pin)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("CheckPINValidity");
if(ptr->head<MSISDN_HEAD_NUM && ptr->tail< UNIT_STORE_ACCOUNT)
{
if(!(strncmp(shmp->prepaid_info[ptr->head][ptr->tail].pin,
pin,
MAX_PIN_LEN)))
return 1;
else
return 0;
}
return 0;
}
int GetCardSystemParam(u_char cos_id,u_short faceValue)
{
int i;
COSTable *cosTableItem;
PutLogFunID("GetCardSystemParam");
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
if(faceValue == 0) return -1;
for(i=0;i<MaxRechargeCardType;i++)
{
if(cosTableItem->rechargeCardValidity[i].cardCredit == faceValue)
return i;
}
return -1;
}
int GetCardSystemParamByNearestValue(u_char cos_id, u_short faceValue)
{
int i, ret = -1;
COSTable *cosTableItem;
u16 maxCredit = 0;
PutLogFunID("GetCardSystemParamByNearestValue");
if (faceValue == 0)
{
return -1;
}
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
for (i=0; i<MaxRechargeCardType; i++)
{
if (faceValue < cosTableItem->rechargeCardValidity[i].cardCredit)
{
continue;
}
if (maxCredit >= cosTableItem->rechargeCardValidity[i].cardCredit)
{
continue;
}
maxCredit = cosTableItem->rechargeCardValidity[i].cardCredit;
ret = i;
}
return ret;
}
void UpdateAccountCallCDR(_account_info *ptr,
char *msisdn,u_long timestamp,int calltype)
{
int len;
char buf[32];
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateAccountCallCDR");
if(ptr->head<MSISDN_HEAD_NUM && ptr->tail<UNIT_STORE_ACCOUNT)
{
shmp->prepaid_info[ptr->head][ptr->tail].last_call_type = calltype;
shmp->prepaid_info[ptr->head][ptr->tail].last_call_date = timestamp;
len = strlen(msisdn);
if(len % 2 == 1)
{
strcpy(buf,msisdn);
strcat(buf,"F");
ppsAsciiToBcdR(shmp->prepaid_info[ptr->head][ptr->tail].last_call_number,buf,len+1);
}
else
{
ppsAsciiToBcdR(shmp->prepaid_info[ptr->head][ptr->tail].last_call_number,msisdn,len);
}
shmp->prepaid_info[ptr->head][ptr->tail].last_call_number[MAX_MSISDN_BLEN-1] = len;
}
}
void UpdateAccountLastCDR(_state_data *shmp)
{
int instance;
PutLogFunID("UpdateAccountLastCallCDR");
switch(shmp->context_info.callType)
{
case CT_MO_CALL:
UpdateAccountCallCDR(&shmp->caller_info,
(char *)shmp->charge_info.number,
shmp->cdr_info.seizuretime,
LST_MO_CALL);
AccountLatchFlagCheck(shmp->caller_info.head,shmp->caller_info.tail);
instance = shmp->caller_info.head * UNIT_STORE_ACCOUNT
+ shmp->caller_info.tail;
SendAccountRealSync(instance,0.0,0.0,OMC_OCODE_EDIT);
break;
case CT_MT_CALL:
UpdateAccountCallCDR(&shmp->called_info,
(char *)shmp->charge_info.number,
shmp->cdr_info.seizuretime,
LST_MT_CALL);
AccountLatchFlagCheck(shmp->called_info.head,shmp->called_info.tail);
instance = shmp->called_info.head * UNIT_STORE_ACCOUNT
+ shmp->called_info.tail;
SendAccountRealSync(instance,0.0,0.0,OMC_OCODE_EDIT);
break;
case CT_MF_CALL:
UpdateAccountCallCDR(&shmp->caller_info,
(char *)shmp->charge_info.number,
shmp->cdr_info.seizuretime,
LST_MF_CALL);
AccountLatchFlagCheck(shmp->caller_info.head,shmp->caller_info.tail);
instance = shmp->caller_info.head * UNIT_STORE_ACCOUNT
+ shmp->caller_info.tail;
SendAccountRealSync(instance,0.0,0.0,OMC_OCODE_EDIT);
break;
case CT_MO_SM:
UpdateAccountCallCDR(&shmp->caller_info,
(char *)shmp->charge_info.number,
shmp->cdr_info.seizuretime,
LST_MO_SMS);
AccountLatchFlagCheck(shmp->caller_info.head,shmp->caller_info.tail);
instance = shmp->caller_info.head * UNIT_STORE_ACCOUNT
+ shmp->caller_info.tail;
SendAccountRealSync(instance,0.0,0.0,OMC_OCODE_EDIT);
break;
}
}
void
UpdateExpiration(_state_data *stashmp)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
long expiration = 0,i_expiration = 0;
u_short valid_time, /* outgoing call */
i_valid_time, /* incoming call */
faceValue;
int index,cos_id;
_account_info *ptr;
COSTable *cosTableItem;
PutLogFunID("UpdateExpiration");
ptr = &stashmp->caller_info;
if(ptr->head>=MSISDN_HEAD_NUM || ptr->tail>=UNIT_STORE_ACCOUNT)
return;
cos_id = shmp->prepaid_info[ptr->head][ptr->tail].cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
valid_time = GetRechargeCardValidTime(stashmp);
if(valid_time<=0) valid_time = 30;
i_valid_time = valid_time;
faceValue = GetRechargeCardFaceValue(stashmp);
expiration = shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date;
i_expiration = shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date;
if((index=GetCardSystemParam(cos_id,faceValue))>=0){
valid_time = cosTableItem->rechargeCardValidity[index].moValidity;
i_valid_time = cosTableItem->rechargeCardValidity[index].mtValidity;
}
if(cosTableItem->accountValidity[0].actionAfterRecharge)
{
if(expiration<(valid_time*24*3600+tvnow.tv_sec))
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date =
valid_time*24*60*60 + tvnow.tv_sec;
if(i_expiration<(i_valid_time*24*3600+tvnow.tv_sec))
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date =
i_valid_time*24*60*60 + tvnow.tv_sec;
}
else
{
if(tvnow.tv_sec > expiration)
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date =
valid_time*24*60*60 + tvnow.tv_sec;
else{
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date +=
valid_time*24*60*60;
}
if(tvnow.tv_sec > i_expiration)
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date =
i_valid_time*24*60*60 + tvnow.tv_sec;
else{
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date +=
i_valid_time*24*60*60;
}
}
if(cosTableItem->accountValidity[0].maxAccountValidityDays<=0)
cosTableItem->accountValidity[0].maxAccountValidityDays = 730;
if(shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date> tvnow.tv_sec
+ cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600)
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date =
tvnow.tv_sec + cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600;
if(shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date> tvnow.tv_sec
+cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600)
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date =
tvnow.tv_sec + cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600;
}
void UpdateExpirationForRechargeCard(_account_info *ptr, u_short valid_time, u_short faceValue)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
long expiration = 0,i_expiration = 0;
u_short i_valid_time; /* incoming call */
int index, cos_id;
COSTable *cosTableItem;
PutLogFunID("UpdateExpirationForRechargeCard");
if(ptr->head>=MSISDN_HEAD_NUM || ptr->tail>=UNIT_STORE_ACCOUNT)
{
return;
}
if(OCS_with_external_CRM())
{
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date =
valid_time*24*60*60 + tvnow.tv_sec;
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date =
valid_time*24*60*60 + tvnow.tv_sec;
return;
}
cos_id = shmp->prepaid_info[ptr->head][ptr->tail].cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
if(valid_time<=0) valid_time = 30;
i_valid_time = valid_time;
expiration = shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date;
i_expiration = shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date;
if((index=GetCardSystemParamByNearestValue(cos_id, faceValue))>=0){
valid_time = cosTableItem->rechargeCardValidity[index].moValidity;
i_valid_time = cosTableItem->rechargeCardValidity[index].mtValidity;
}
if(cosTableItem->accountValidity[0].actionAfterRecharge)
{
if(expiration<(valid_time*24*3600+tvnow.tv_sec))
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date =
valid_time*24*60*60 + tvnow.tv_sec;
if(i_expiration<(i_valid_time*24*3600+tvnow.tv_sec))
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date =
i_valid_time*24*60*60 + tvnow.tv_sec;
}
else
{
if(tvnow.tv_sec > expiration)
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date =
valid_time*24*60*60 + tvnow.tv_sec;
else{
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date +=
valid_time*24*60*60;
}
if(tvnow.tv_sec > i_expiration)
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date =
i_valid_time*24*60*60 + tvnow.tv_sec;
else{
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date +=
i_valid_time*24*60*60;
}
}
if(cosTableItem->accountValidity[0].maxAccountValidityDays<=0)
{
cosTableItem->accountValidity[0].maxAccountValidityDays = 730;
}
if(shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date> tvnow.tv_sec
+ cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600)
{
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date =
tvnow.tv_sec + cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600;
}
if(shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date> tvnow.tv_sec
+cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600)
{
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date =
tvnow.tv_sec + cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600;
}
}
void
UpdateExpirationFirstCharge(_state_data *stashmp)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
u_short valid_time, /* outgoing call */
i_valid_time; /* incoming call */
int index,cos_id;
u_short faceValue;
_account_info *ptr;
COSTable *cosTableItem;
PutLogFunID("UpdateExpirationFirstCharge");
ptr = &stashmp->caller_info;
if(ptr->head>=MSISDN_HEAD_NUM) {
return;
}
cos_id = shmp->prepaid_info[ptr->head][ptr->tail].cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
valid_time = GetRechargeCardValidTime(stashmp);
i_valid_time = valid_time;
faceValue = GetRechargeCardFaceValue(stashmp);
if((index=GetCardSystemParam(cos_id,faceValue))>=0){
valid_time = cosTableItem->rechargeCardValidity[index].moValidity;
i_valid_time = cosTableItem->rechargeCardValidity[index].mtValidity;
}
shmp->prepaid_info[ptr->head][ptr->tail].mo_expiration_date =
valid_time*24*60*60 + tvnow.tv_sec ;
shmp->prepaid_info[ptr->head][ptr->tail].mt_expiration_date =
i_valid_time*24*60*60 + tvnow.tv_sec ;
}
void
UpdateExpirationFirstInquiry(_account_info *ptr, u_short valid_time)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
_prepaid_info *user_ptr = NULL;
COSTable *cosTableItem;
int cos_id= 0, bundle_plan_id=0;
PutLogFunID("UpdateExpirationFirstInquiry");
if(ptr->head>=MSISDN_HEAD_NUM || ptr->tail>=UNIT_STORE_ACCOUNT)
return;
cos_id = ptr->cos_id%MaxCosTableItem;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
user_ptr = &shmp->prepaid_info[ptr->head][ptr->tail];
user_ptr->mo_expiration_date = valid_time*24*60*60 + tvnow.tv_sec ;
user_ptr->mt_expiration_date = valid_time*24*60*60 + tvnow.tv_sec ;
bundle_plan_id = cosTableItem->accountValidity[0].bundlePlanIDWhenActivated;
if( bundle_plan_id > 0 && bundle_plan_id < MAX_BUNDLE_PLANS)
{
user_ptr->bundle_info.validity_date = user_ptr->mo_expiration_date;
user_ptr->bundle_info.data = ppsParam.ppsTables.bundlePlans[bundle_plan_id].data * 1024 * 1024LL;
user_ptr->bundle_info.mo_voice = ppsParam.ppsTables.bundlePlans[bundle_plan_id].mo_voice * 60;
user_ptr->bundle_info.mt_voice = ppsParam.ppsTables.bundlePlans[bundle_plan_id].mt_voice * 60;
user_ptr->bundle_info.sms = ppsParam.ppsTables.bundlePlans[bundle_plan_id].sms;
}
}
void
UpdateAccountExpiration(int head, int tail, u_short faceValue,u_short valid_time)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
u_long expiration=0,i_expiration=0;
short index, i_valid_time;
int cos_id;
COSTable *cosTableItem;
PutLogFunID("UpdateAccountExpiration");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
expiration = shmp->prepaid_info[head][tail].mo_expiration_date;
i_expiration = shmp->prepaid_info[head][tail].mt_expiration_date;
i_valid_time = valid_time;
cos_id = shmp->prepaid_info[head][tail].cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
if((index=GetCardSystemParam(cos_id,faceValue))>=0){
valid_time = cosTableItem->rechargeCardValidity[index].moValidity;
i_valid_time = cosTableItem->rechargeCardValidity[index].mtValidity;
}
if(cosTableItem->accountValidity[0].actionAfterRecharge)
{
if(expiration<(valid_time*24*3600+tvnow.tv_sec))
shmp->prepaid_info[head][tail].mo_expiration_date =
valid_time*24*60*60 + tvnow.tv_sec;
if(i_expiration<(i_valid_time*24*3600+tvnow.tv_sec))
shmp->prepaid_info[head][tail].mt_expiration_date =
i_valid_time*24*60*60 + tvnow.tv_sec;
}
else
{
if(tvnow.tv_sec > expiration)
shmp->prepaid_info[head][tail].mo_expiration_date =
valid_time*24*60*60 + tvnow.tv_sec;
else{
shmp->prepaid_info[head][tail].mo_expiration_date +=
valid_time*24*60*60;
}
if(tvnow.tv_sec > i_expiration)
shmp->prepaid_info[head][tail].mt_expiration_date =
i_valid_time*24*60*60 + tvnow.tv_sec;
else{
shmp->prepaid_info[head][tail].mt_expiration_date +=
i_valid_time*24*60*60;
}
}
if(cosTableItem->accountValidity[0].maxAccountValidityDays<=0)
{
cosTableItem->accountValidity[0].maxAccountValidityDays = 730;
}
if(shmp->prepaid_info[head][tail].mo_expiration_date> tvnow.tv_sec
+ cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600)
{
shmp->prepaid_info[head][tail].mo_expiration_date =
tvnow.tv_sec + cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600;
}
if(shmp->prepaid_info[head][tail].mt_expiration_date> tvnow.tv_sec
+cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600)
{
shmp->prepaid_info[head][tail].mt_expiration_date =
tvnow.tv_sec + cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600;
}
}
}
int
UpdateAccountStatusFromNormalToSuspendedforExpiration(_prepaid_info *pUsrInfo, int head, int tail)
{
if(pUsrInfo == NULL)
return 0;
if(pUsrInfo->mo_expiration_date < tvnow.tv_sec)
{
if(pUsrInfo->status == T_NORMAL)
{
pUsrInfo->status = T_SUSPEND;
SendAccountRealSync(head*UNIT_STORE_ACCOUNT+tail, 0.00, 0.00, OMC_OCODE_EDIT );
}
}
return 0;
}
int
GetAccountStatus(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetAccountStatus");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
if(shmp->prepaid_info[ptr->head][ptr->tail].balance>=ppsParam.serviceControl.maxBalance)
shmp->prepaid_info[ptr->head][ptr->tail].status = T_SUSPEND;
if(shmp->prepaid_info[ptr->head][ptr->tail].msisdn[MAX_MSISDN_BLEN-1]<=2)
{
shmp->prepaid_info[ptr->head][ptr->tail].status = T_FRESH;
return T_EXTERNAL;
}
return shmp->prepaid_info[ptr->head][ptr->tail].status;
}
return T_EXTERNAL;
}
int GetAccountCosID(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetAccountCosID");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
return shmp->prepaid_info[ptr->head][ptr->tail].cos_id;
}
return 0;
}
int GetSerivceNumberFlagPerCos(u8 cos_id, u8 service_type, u8 call_type);
int GetServiceNumberFlag(_state_data *shmp, u8 service_pos)
{
int match_flag = 0;
if(shmp->context_info.callType == CT_MO_CALL)
{
match_flag = GetSerivceNumberFlagPerCos(shmp->caller_info.cos_id, service_pos, 0);
}
else if(shmp->context_info.callType == CT_MO_SM )
{
match_flag = GetSerivceNumberFlagPerCos(shmp->caller_info.cos_id, service_pos, 1);
}
else if(shmp->context_info.callType == CT_USSD)
match_flag = GetSerivceNumberFlagPerCos(shmp->caller_info.cos_id, service_pos, 2);
return match_flag;
}
int GetServiceType_0(_state_data *shmp)
{
int len0,len1;
char buf[32];
char destination[32];
strcpy(destination, (char *)shmp->called_info.number);
if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[HotLineNumberPosition].number)==0)
{
return SRV_CALL_HOTLINE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[InquiryNumberPosition].number)==0)
{
return SRV_INQUIRY;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[ScratchCardRechargeNumberPosition].number)==0)
{
return SRV_SCRATCH_CARD_RECHARGE;
//return SRV_RECHARGE_2TYPES;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[CreditCardRechargeNumberPosition].number)==0)
{
return SRV_BUNDLE_PLAN; //SRV_CREDIT_CARD_RECHARGE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[ThirdPartyRechargeNumberPosition].number)==0)
{
return SRV_THIRD_PARTY_RECHARGE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[RechargeNumberPosition].number)==0)
{
return SRV_RECHARGE_2TYPES;
//return SRV_SCRATCH_CARD_RECHARGE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[PalimRegisterNumberPosition].number) == 0)
{
shmp->process_info.palim_auto_register = 1;
return SRV_SCRATCH_CARD_RECHARGE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[PoolAccountPosition].number)==0)
{
return SRV_POOL_ACCOUNT;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[FeeTransferPosition].number)==0)
{
return SRV_FEE_TRANSFER;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number)==0)
{
return SRV_FREE_SMS;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[CallMeBackPosition].number)==0)
{
return SRV_CALL_ME_BACK;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[TellMeNumber].number)==0)
{
return SRV_TELL_ME_NUMBER;
}
/*
else if(IsCRDServiceNumber(destination))
{
return SRV_CRD;
}
else if(IsPSTNMaitenance(destination))
{
return SRV_OTHER_VMS_MAITENANCE;
}
else if(IsVMSDeposit(destination))
{
return SRV_VMS_DEPOSIT;
}
*/
else if(IsCallingCardNumber(destination))
{/*calling card */
return SRV_CALLINGCARD_MANAGE;
}
/*
else if(IsDirectAccess(destination))
{
return SRV_DIRECT_ACCESS;
}
else if(IsVMSReservedFunc(destination))
{
return SRV_RESERVED_FUN;
}*/
else
{
len0 = strlen((char *)ppsParam.ppsTables.serviceNumber[CallMeBackPosition].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination,
(char *)ppsParam.ppsTables.serviceNumber[CallMeBackPosition].number,len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number, destination);
shmp->process_info.all_in_one_input_flag = 1;
return SRV_CALL_ME_BACK;
}
}
len0 = strlen((char *)ppsParam.ppsTables.serviceNumber[ScratchCardRechargeNumberPosition].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination, (char *)ppsParam.ppsTables.serviceNumber[ScratchCardRechargeNumberPosition].number, len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number, destination);
return SRV_RECHARGE_ONE_INPUT;
}
}
len0 = strlen((char *)ppsParam.ppsTables.serviceNumber[PalimRegisterNumberPosition].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination,
(char *)ppsParam.ppsTables.serviceNumber[PalimRegisterNumberPosition].number,len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number,destination);
shmp->process_info.palim_auto_register = 1;
return SRV_RECHARGE_ONE_INPUT;
}
}
return SRV_NORMAL_MO_CALL;
}
return SRV_NORMAL_MO_CALL;
}
int GetServiceType(_state_data *shmp)
{
int len0,len1;
char buf[32];
char destination[32];
strcpy(destination, (char *)shmp->called_info.number);
shmp->process_info.tcos= NORMAL_RELEASE;
if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[HotLineNumberPosition].number)==0)
{
if(GetServiceNumberFlag(shmp, HotLineNumberPosition))
return SRV_CALL_HOTLINE;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[InquiryNumberPosition].number)==0)
{
if(GetServiceNumberFlag(shmp, InquiryNumberPosition))
return SRV_INQUIRY;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[ScratchCardRechargeNumberPosition].number)==0)
{
if(GetServiceNumberFlag(shmp, ScratchCardRechargeNumberPosition))
return SRV_SCRATCH_CARD_RECHARGE;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
//return SRV_RECHARGE_2TYPES;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[CreditCardRechargeNumberPosition].number)==0)
{
if(GetServiceNumberFlag(shmp, CreditCardRechargeNumberPosition))
return SRV_CREDIT_CARD_RECHARGE;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[ThirdPartyRechargeNumberPosition].number)==0)
{
if(GetServiceNumberFlag(shmp, ThirdPartyRechargeNumberPosition))
return SRV_THIRD_PARTY_RECHARGE;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[RechargeNumberPosition].number)==0)
{
if(GetServiceNumberFlag(shmp, RechargeNumberPosition))
return SRV_RECHARGE_2TYPES;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
//return SRV_SCRATCH_CARD_RECHARGE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[PalimRegisterNumberPosition].number) == 0)
{
if(GetServiceNumberFlag(shmp, PalimRegisterNumberPosition))
{
shmp->process_info.palim_auto_register = 1;
return SRV_SCRATCH_CARD_RECHARGE;
}
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[PoolAccountPosition].number)==0)
{
if(GetServiceNumberFlag(shmp, PoolAccountPosition))
return SRV_POOL_ACCOUNT;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[FeeTransferPosition].number)==0)
{
if(GetServiceNumberFlag(shmp, FeeTransferPosition))
return SRV_FEE_TRANSFER;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number)==0)
{
if(GetServiceNumberFlag(shmp, FreeServicePosition))
return SRV_FREE_SMS;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[CallMeBackPosition].number)==0)
{
if(GetServiceNumberFlag(shmp, CallMeBackPosition))
return SRV_CALL_ME_BACK;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.serviceNumber[TellMeNumber].number)==0)
{
if(GetServiceNumberFlag(shmp, TellMeNumber))
return SRV_TELL_ME_NUMBER;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}/*
else if(IsCRDServiceNumber(destination))
{
return SRV_CRD;
}
else if(IsPSTNMaitenance(destination))
{
return SRV_OTHER_VMS_MAITENANCE;
}
else if(IsVMSDeposit(destination))
{
return SRV_VMS_DEPOSIT;
}
else if(IsOprNumber(destination))
{
if(GetServiceNumberFlag(shmp, OPRNumberPosition))
return SRV_OPR_MANAGE;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}*/
else if(IsCallingCardNumber(destination))
{/*calling card */
if(GetServiceNumberFlag(shmp, VirtualCallingCardNumberPosition))
return SRV_CALLINGCARD_MANAGE;
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
/*
else if(IsDirectAccess(destination))
{
return SRV_DIRECT_ACCESS;
}
else if(IsVMSReservedFunc(destination))
{
return SRV_RESERVED_FUN;
}*/
else
{
len0 = strlen((char *)ppsParam.ppsTables.serviceNumber[CallMeBackPosition].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination,
(char *)ppsParam.ppsTables.serviceNumber[CallMeBackPosition].number,len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number,destination);
if(GetServiceNumberFlag(shmp, CallMeBackPosition))
{
shmp->process_info.all_in_one_input_flag = 1;
return SRV_CALL_ME_BACK;
}
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
}
len0 = strlen((char *)ppsParam.ppsTables.serviceNumber[ScratchCardRechargeNumberPosition].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination, (char *)ppsParam.ppsTables.serviceNumber[ScratchCardRechargeNumberPosition].number,len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number, destination);
if(GetServiceNumberFlag(shmp, ScratchCardRechargeNumberPosition))
{
return SRV_RECHARGE_ONE_INPUT;
}
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
}
len0 = strlen((char *)ppsParam.ppsTables.serviceNumber[PalimRegisterNumberPosition].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination,
(char *)ppsParam.ppsTables.serviceNumber[PalimRegisterNumberPosition].number,len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number,destination);
if(GetServiceNumberFlag(shmp, PalimRegisterNumberPosition))
{
shmp->process_info.palim_auto_register = 1;
return SRV_RECHARGE_ONE_INPUT;
}
else
{
shmp->process_info.tcos= SRVICE_NOT_SUBSCRIBERED;
shmp->process_info.voiceID = SERIVCE_NOT_APPLIED;
}
}
}
return SRV_NORMAL_MO_CALL;
}
return SRV_NORMAL_MO_CALL;
}
int GetUssdServiceType(_state_data *shmp)
{
int len0,len1;
char buf[128];
char destination[128];
strcpy(destination, (char *)shmp->called_info.number);
if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_HOTLINE].number)==0)
{
return SRV_CALL_HOTLINE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_INQUIRY].number)==0)
{
return SRV_INQUIRY;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_RECHARGE].number)==0)
{
return SRV_SCRATCH_CARD_RECHARGE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_FEE_TRANSFER].number)==0)
{
return SRV_FEE_TRANSFER;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_CALL_ME_BACK].number)==0)
{
return SRV_CALL_ME_BACK;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_TELL_ME_NUMBER].number)==0)
{
return SRV_TELL_ME_NUMBER;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_FRIEND_FAMILY_QUERY].number)==0)
{
return SRV_FAVORITE_NUMBER;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_BUNDLE_PLAN].number)==0)
{
return SRV_BUNDLE_PLAN;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_BUNDLE_QUERY].number)==0)
{
return SRV_BUNDLE_QUERY;
}
else
{
len0 = strlen((char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_CALL_ME_BACK].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination,
(char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_CALL_ME_BACK].number,len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number,destination);
shmp->process_info.all_in_one_input_flag = 1;
return SRV_CALL_ME_BACK;
}
}
len0 = strlen((char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_RECHARGE].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_RECHARGE].number,len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number, destination);
return SRV_RECHARGE_ONE_INPUT;
}
}
}
return SRV_NORMAL_MO_CALL;
}
int GetUssdServiceType_1(_state_data *shmp)
{
int len0,len1;
char buf[32];
char destination[32];
strcpy(destination, (char *)shmp->called_info.number);
if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_HOTLINE].number)==0)
{
if(GetServiceNumberFlag(shmp, HotLineNumberPosition))
return SRV_CALL_HOTLINE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_INQUIRY].number)==0)
{
if(GetServiceNumberFlag(shmp, InquiryNumberPosition))
return SRV_INQUIRY;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_RECHARGE].number)==0)
{
if(GetServiceNumberFlag(shmp, ScratchCardRechargeNumberPosition))
return SRV_SCRATCH_CARD_RECHARGE;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_FEE_TRANSFER].number)==0)
{
if(GetServiceNumberFlag(shmp, FeeTransferPosition))
return SRV_FEE_TRANSFER;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_CALL_ME_BACK].number)==0)
{
if(GetServiceNumberFlag(shmp, CallMeBackPosition))
return SRV_CALL_ME_BACK;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_TELL_ME_NUMBER].number)==0)
{
if(GetServiceNumberFlag(shmp, TellMeNumber))
return SRV_TELL_ME_NUMBER;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_FRIEND_FAMILY_QUERY].number)==0)
{
if(GetServiceNumberFlag(shmp, FriendFamilyPosition))
return SRV_FAVORITE_NUMBER;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_BUNDLE_PLAN].number)==0)
{
return SRV_BUNDLE_PLAN;
}
else if(strcmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_BUNDLE_QUERY].number)==0)
{
return SRV_BUNDLE_QUERY;
}
else
{
len0 = strlen((char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_CALL_ME_BACK].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination,
(char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_CALL_ME_BACK].number,len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number,destination);
if(GetServiceNumberFlag(shmp, CallMeBackPosition))
{
shmp->process_info.all_in_one_input_flag = 1;
return SRV_CALL_ME_BACK;
}
}
}
len0 = strlen((char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_RECHARGE].number);
if(len0 !=0)
{
len1 = strlen(destination);
if(len1>= 6 +len0)
if(strncmp(destination, (char *)ppsParam.ppsTables.ussdServiceNumber[USSD_OC_RECHARGE].number,len0)==0)
{
strcpy(buf,&destination[len0]);
strcpy(destination,buf);
destination[len1-len0] = 0;
strcpy((char *)shmp->called_info.number, destination);
if(GetServiceNumberFlag(shmp, ScratchCardRechargeNumberPosition))
return SRV_RECHARGE_ONE_INPUT;
}
}
}
return SRV_NORMAL_MO_CALL;
}
int GetUssdServiceKey(u_char serviceKey)
{
int i;
PutLogFunID("GetUssdServiceKey");
for(i=USSD_OC_HOTLINE;i<USSD_OC_MAX;i++)
if(ppsParam.ppsTables.ussdServiceKey[i].key == serviceKey)
return i;
return -1;
}
int CheckWetherFavoriteNumber(_account_info *caller, char *called_number)
{
int i,len;
char msisdn[32];
int cos_id;
CosFriendFamilyControl *serviceControlItem;
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("CheckWetherFavoriteNumber");
if(caller->head < MSISDN_HEAD_NUM && caller->tail <UNIT_STORE_ACCOUNT)
{
if(!shmp->prepaid_info[caller->head][caller->tail].favorite_numbers)
return NOT_FAVORITE_NUMBER;
cos_id = shmp->prepaid_info[caller->head][caller->tail].cos_id;
serviceControlItem = &ppsParam.ppsTables.cosTable[cos_id].friendFamilyControl[0];
if(serviceControlItem->balanceThresholdForFriendFamilyCall>GetAccountBalance(caller->head, caller->tail))
return NOT_FAVORITE_NUMBER;
//if F*F PLAN, check total F&F call duraiton here
for(i=0;i<MAX_FAVORITE_NUMBERS;i++)
{
len = shmp->prepaid_info[caller->head][caller->tail].favorite_number[i][MAX_MSISDN_BLEN-1];
if(len>MAX_MSISDN_ALEN || len<2)
continue;
BcdToAscii(msisdn,
shmp->prepaid_info[caller->head][caller->tail].favorite_number[i],
MAX_MSISDN_ALEN);
msisdn[len] = 0;
CutUnknownPrefix(msisdn);
//CheckWetherLocalNumber(msisdn);
if(strcmp(msisdn,called_number)==0)
return FAVORITE_NUMBER;
}
}
return NOT_FAVORITE_NUMBER;
}
int
GetAccountID(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
_prepaid_info *user_info=NULL;
PutLogFunID("GetAccountID");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
user_info = &shmp->prepaid_info[ptr->head][ptr->tail];
if(user_info->msisdn[MAX_MSISDN_BLEN-1]>=MIN_MSISDN_ALEN && user_info->msisdn[MAX_MSISDN_BLEN-1]<=MAX_MSISDN_ALEN)
{
return user_info->crm_info.account_id;
}
else
return 0;
}
return 0;
}
int
GetAccountCUG(_account_info *ptr)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
_prepaid_info *user_info=NULL;
PutLogFunID("GetAccountCUG");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
user_info = &shmp->prepaid_info[ptr->head][ptr->tail];
if(user_info->msisdn[MAX_MSISDN_BLEN-1]>=MIN_MSISDN_ALEN && user_info->msisdn[MAX_MSISDN_BLEN-1]<=MAX_MSISDN_ALEN)
{
if(user_info->crm_info.vas_cug_state != 0)//cug service is blocked for rent charge failed
return NOT_CUG_ACCOUNT;
return user_info->cug_id;
}
else
return NOT_CUG_ACCOUNT;
}
return NOT_CUG_ACCOUNT;
}
int GetDiscount(long timestamp,u_char discount_id)
{
int holiday_flag;
_tariff_private *shmp;
struct tm tm, *timep;
int discount=0;
int wday=0;
PutLogFunID("GetDiscount");
shmp = blf_shmp;
timep = (struct tm *) &tm;
timep = (struct tm *) localtime( (time_t *)&timestamp );
if(timep == NULL)
{
DebugMsg(debugmib.display.asciiOut, "Get Discount time error: %d", timestamp);
return 100;
}
holiday_flag = shmp->holiday_flag[timep->tm_mon][timep->tm_mday-1];// advanced->Tariff plan->Holiday
wday = (holiday_flag ? 7 : timep->tm_wday);
#if DEBUG1
DebugMsg(debugmib.display.asciiOut, "Tm month: %d Tm mday: %d Holiday flag: %d",
timep->tm_mon, timep->tm_mday, holiday_flag);
#endif
discount = shmp->bill_discount[discount_id][timep->tm_hour][wday];// advanced->Tariff plan->Discount
#if DEBUG1
DebugMsg(debugmib.display.asciiOut, "Type: %d Hour: %d Week day: %d Discount: %d",
id, timep->tm_hour, wday, discount);
#endif
if(discount < 0)
discount = 0;
return discount;
}
void set_truncation_flag(int flag)
{
ppsParam.serviceControl.truncation_flag = flag;
}
int get_truncation_flag()
{
return ppsParam.serviceControl.truncation_flag;
}
int SetTcpSyncFlag(int flag)
{
DebugMsg(debugmib.display.asciiOut,"Current tcp sync flag: %d", ppsParam.serviceControl.tcp_sync_flag);
if(flag)
ppsParam.serviceControl.tcp_sync_flag = 1;
else
ppsParam.serviceControl.tcp_sync_flag = 0;
DebugMsg(debugmib.display.asciiOut,"New tcp sync flag: %d", ppsParam.serviceControl.tcp_sync_flag);
return 1;
}
float ChargeGprsAccountBalance(_state_data *shmp,int real_duration)
{
int i=0,j;
int discount=0;
float charge=0;
int itimes=0, unit_time=60;
int duration, begin_time;
_bill_tariff *ptar;
PutLogFunID("ChargeAccountBalance");
begin_time = shmp->cdr_info.answertime,
ptar = &shmp->process_info.tariff;
duration = real_duration;
duration -= ptar->free_time;
if(duration<=0) return (charge = 0);
if ((unit_time = ptar->unit_time) <= 0)
unit_time = 60;
itimes = (ceil)((double) duration / unit_time);
discount = GetDiscount(begin_time,ptar->discountID);
for (i=1; i<=itimes; i++)
{
if (i <= ptar->mini_unit )
{
for(j=0;j < ptar->mini_unit;j++)
{
charge += BillingFormula(shmp,ptar,begin_time);
begin_time += unit_time;
}
charge = (charge + ptar->adjustment);
i = ptar->mini_unit;
}
else
{
charge = charge + BillingFormula(shmp,ptar,begin_time);
begin_time += unit_time;
}
}
charge = (charge * discount)/100;
return charge;
}
int GetValidTime(_state_data *shmp,int begin_time, _bill_tariff *ptar,
float balance, int init_bill, int overdraft)
{
int valid_time = 0;
float charge=0, amount=0;
int cos_id;
COSTable *cosTableItem;
PutLogFunID("GetValidTime");
cos_id = shmp->called_info.cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
if (init_bill == 0)
valid_time = ptar->unit_time * ptar->mini_unit;
else
valid_time = ptar->unit_time;
if (valid_time <= 0)
valid_time = 60;
charge = TimeToCharge(shmp,ptar, valid_time, begin_time,init_bill);
amount = balance - charge + overdraft;
#if DEBUG1
DebugMsg(debugmib.display.asciiOut,
"GetValid time: balance: %.0f charge: %.0f draft: %d amount: %.0f",
balance, charge, overdraft, amount);
#endif
/*How to get left seconds of account???
2003-10-07
*/
if(charge==0)
{
/* mo call */
if(shmp->context_info.callType != CT_MT_CALL)
{
//if(amount<=0) /* zero balance can't make free mo call */
if(amount<0)
valid_time = 0;
}
else
{
if(cosTableItem->serviceControl[0].mtChargeFlag !=0 )
{ // mt call, charged ,no balance
if(cosTableItem->serviceControl[0].mtBalanceControl == 1)
if(balance+overdraft<cosTableItem->serviceControl[0].mtBalanceThreshold)
valid_time = 0;
}
else
{// mt is free
if(cosTableItem->serviceControl[0].mtChargeFlag == 1)
{ // mt balance threshold used
if(balance+overdraft<cosTableItem->serviceControl[0].mtBalanceThreshold)
valid_time = 0;
}
}
}
}
else
{
if(amount<0)
valid_time = 0;
if(shmp->context_info.callType == CT_MT_CALL)
if(cosTableItem->serviceControl[0].mtChargeFlag == 1)
{
if(balance+overdraft<cosTableItem->serviceControl[0].mtBalanceThreshold)
valid_time = 0;
}
}
/*
if (amount < 0 && charge >= 0)
valid_time = 0;
*/
return (valid_time*CYCLE_STATE_INTERVAL);
}
int GetMaxCallDuration(_state_data *shmp)
{
int /*init_flag=0 , */discount, maxDuration=0,free_time=0;
float balance;
_bill_tariff *ptar, tariff;
//int j;
//float charge;
u32 calTime;
int init_charge_cycle = 0;
PutLogFunID("GetMaxCallDuration");
if(shmp->process_info.serviceType == SRV_CRD
||
(shmp->process_info.serviceType == SRV_NORMAL_MO_CALL
&&
shmp->process_info.callConnected == 1
&&
!ppsParam.serviceControl.vms_allways_go))
{
maxDuration = 12 * ONE_MINUTE_STATE_TIME ;
shmp->process_info.maxCallDuration = maxDuration;
return maxDuration;
}
ptar = &tariff;
memcpy(ptar, &shmp->process_info.tariff, sizeof(_bill_tariff));
if(ptar->unit_time<=0)
ptar->unit_time = 60;
if(0)
DebugMsg(debugmib.display.asciiOut, " %s:%d , tariff: %.2f+%.2f vs %.2f+%.2f",
__FUNCTION__, __LINE__,
shmp->process_info.tariff.tierRating.rating[0].base_fee,
shmp->process_info.tariff.tierRating.rating[0].long_distance_fee,
ptar->tierRating.rating[0].base_fee,
ptar->tierRating.rating[0].long_distance_fee);
if (shmp->process_info.ro_if.gy_ro_enable)
{
init_charge_cycle = ptar->free_time;// Ro: shmp->process_info.duration is in second.
}
else
{
init_charge_cycle = ptar->free_time*CYCLE_STATE_INTERVAL;
}
if(shmp->process_info.duration < init_charge_cycle)
{
free_time = ptar->free_time;
maxDuration = free_time;
//init_flag = 1;
}
else
{
/*
init_charge_cycle = (ptar->free_time+ptar->mini_unit*ptar->unit_time)*CYCLE_STATE_INTERVAL;
if(shmp->process_info.duration < init_charge_cycle)
{
init_flag = 1;
}
*/
}
discount = GetDiscount(tvnow.tv_sec, ptar->discountID);
if(discount <= 0)// free call
{
maxDuration = MAX_CALL_DURATION;
}
else
{
if(shmp->context_info.callType == CT_MT_CALL)
balance = (int)GetBalanceWithPromotionControl(shmp,&shmp->called_info) + GetOverdraft(&shmp->called_info);
else
balance = (int)GetBalanceWithPromotionControl(shmp,&shmp->caller_info) + GetOverdraft(&shmp->caller_info);
if(balance<0)
return 0;
calTime = preLeftTime(shmp,balance,ptar);
maxDuration += calTime; // free_time + pre left
}
shmp->process_info.maxCallDuration = maxDuration;
return maxDuration;
}
void
EncryptCardHRN(char *card_hrn,u_char *card_pwd)
{
char pinkey[32],tmp_hrn[32];
u_char u_buf[32];
int len;
//PutLogFunID("EncryptCardHRN");
len = strlen(card_hrn);
/*
if(len == 10) // add for PNCC
{
StringCat(card_hrn,"00",12);
memcpy(pinkey, card_hrn, 6);
pinkey[6] = 0;
StringCat(pinkey, "0", 8);
EncryptPIN(card_pwd, card_hrn, PAN_KEY, pinkey);
}
else if(len == 11) // for Solomon, 2006-11-15
{
StringCat(card_hrn,"0",12);
memcpy(pinkey, card_hrn, 6);
pinkey[6] = 0;
StringCat(pinkey, "0", 8);
EncryptPIN(card_pwd, card_hrn, PAN_KEY, pinkey);
}
*/
if(len<10 || len>16) return;
if(len<12)
{
strcpy(tmp_hrn,card_hrn);
StringCat(tmp_hrn,"0",16);
AsciiToBcd(u_buf,tmp_hrn,16);
des(card_pwd,u_buf, (unsigned char *)PAN_KEY,0);
}
else if(len==12)
{
memcpy(pinkey, card_hrn, 6);
pinkey[6] = 0;
StringCat(pinkey, "0", 8);
EncryptPIN(card_pwd, card_hrn, PAN_KEY, (unsigned char *)pinkey);
}
else if(len == 14)
{
memcpy(pinkey, card_hrn, 7);
pinkey[7] = 0;
StringCat(pinkey, "0", 8);
EncryptPIN(card_pwd, card_hrn, PAN_KEY, (unsigned char *)pinkey);
}
else if(len==16)
{
AsciiToBcd(u_buf,card_hrn,16);
des(card_pwd,u_buf, (unsigned char *)PAN_KEY,0);
}
else
{
if(0)
DebugMsg(debugmib.display.asciiOut,"\33[31mPwd len:%d error!Must be 12,14,16 \33[0m",len);
}
#if DEBUG1
DebugMsg(debugmib.display.asciiOut, "card hrn: %s pinkey: %s",
card_hrn, pinkey);
#endif
}
u_char
GetAccountZoneID(int head, int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
int cos_id;
COSTable *cosTableItem;
PutLogFunID("GetAccountZoneID");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
cos_id = shmp->prepaid_info[head][tail].cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
return cosTableItem->tariff[0].moTariffID%MAX_ZONE_NUM;
}
return 0;
}
u_char GetAccountMTZoneID(int head, int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
int cos_id;
COSTable *cosTableItem;
PutLogFunID("GetAccountMTZoneID");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
cos_id = shmp->prepaid_info[head][tail].cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
return cosTableItem->tariff[0].mtTariffID%MAX_ZONE_NUM;
}
return 0;
}
int GetAccountLastCallInfo(_account_info *ptr, _last_call_info *pInfo)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetAccountLastCallInfo");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
if(shmp->prepaid_info[ptr->head][ptr->tail].last_call_date>tvnow.tv_sec/2)
{
pInfo->last_call_type =
shmp->prepaid_info[ptr->head][ptr->tail].last_call_type;
pInfo->last_call_date =
shmp->prepaid_info[ptr->head][ptr->tail].last_call_date;
memcpy(pInfo->last_call_number,
shmp->prepaid_info[ptr->head][ptr->tail].last_call_number,
MAX_MSISDN_BLEN);
return 1;
}
}
return 0;
}
int IsSpanCall(_state_data *shmp)
{
PutLogFunID("IsSpanCall");
if (shmp->caller_info.location !=
GetAccountZoneID(shmp->caller_info.head,
shmp->caller_info.tail) )
return TRUE;
else
return FALSE;
}
int IncreaseServiceSM(int head, int tail)
{
_prepaid_info *ptr;
PutLogFunID("IncreaseServiceSM");
if(head<MSISDN_HEAD_NUM){
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
if(ptr->free_sm_counter<0x7F)
return (++ptr->free_sm_counter);
return ptr->free_sm_counter;
}
return 0;
}
int IncreaseFavoriteNumberChangeCounterByOmc(_prepaid_info *ptr)
{
PutLogFunID("IncreaseFavoriteNumberChangeCounterByOmc");
if(ptr == NULL)
return 0;
if(ptr->fav_change_counter<0x7F)
return (++ptr->fav_change_counter);
return ptr->fav_change_counter;
}
int IncreaseFavoriteNumberChangeCounter(int head, int tail)
{
_prepaid_info *ptr;
PutLogFunID("IncreaseFavoriteNumberChangeCounter");
if(head<MSISDN_HEAD_NUM)
{
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
if(ptr->fav_change_counter<0x7F)
return (++ptr->fav_change_counter);
return ptr->fav_change_counter;
}
return 0;
}
int GetFriendFamilyChangeCounter(int head, int tail)
{
_prepaid_info *ptr;
PutLogFunID("IncreaseFavoriteNumberChangeCounter");
if(head<MSISDN_HEAD_NUM)
{
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
return ptr->fav_change_counter;
}
return 0;
}
int GetFriendFamilyCounter(int head, int tail)
{
_prepaid_info *ptr;
PutLogFunID("IncreaseFavoriteNumberChangeCounter");
if(head<MSISDN_HEAD_NUM)
{
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
return ptr->favorite_numbers;
}
return 0;
}
int GetAccountFriendFamilyPlanID(int head, int tail)
{
_prepaid_info *ptr;
PutLogFunID("GetAccountFriendFamilyPlanID");
if(head<MSISDN_HEAD_NUM)
{
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
return ptr->favorite_plan_id-1;
}
return -1;
}
int GetFavoriteNumberChangeCharge(_state_data *shmp)
{
int head,tail;
int amount,tariff_id=0;
//_prepaid_info *ptr;
PutLogFunID("BillingFavoriteNumberChange");
head = shmp->caller_info.head;
tail = shmp->caller_info.tail;
if(head>=MSISDN_HEAD_NUM)
return 0;
tariff_id = GetAccountZoneID(head,tail);
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
//ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
amount = ramshm_ptr->tariff_data.comm_tariff[tariff_id].favEditChargeAmount;
return amount;
}
int BillingFavoriteNumberChange(_state_data *shmp)
{
int head,tail;
int amount,tariff_id=0;
_prepaid_info *ptr;
PutLogFunID("BillingFavoriteNumberChange");
head = shmp->caller_info.head;
tail = shmp->caller_info.tail;
if(head>=MSISDN_HEAD_NUM)
return 0;
tariff_id = GetAccountZoneID(head,tail);
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
amount = ramshm_ptr->tariff_data.comm_tariff[tariff_id].favEditChargeAmount;
ptr->balance = ptr->balance - amount;
shmp->caller_info.charge = amount;
return amount;
}
int IsEnableToAddEditFavoriteNumber(_state_data *shmp, int flag)
{/*flag = 0/1, add, edit */
CosFriendFamilyControl *friendFamilyControl;
int cos_id,plan_id=0;
cos_id = shmp->caller_info.cos_id;
friendFamilyControl = &ppsParam.ppsTables.cosTable[cos_id].friendFamilyControl[0];
plan_id = GetAccountFriendFamilyPlanID(shmp->caller_info.head,shmp->caller_info.tail);
if(plan_id>MAX_FAVORITE_PALN)
return 0;
if(plan_id>=0 && flag == 0)
{
if(GetFriendFamilyCounter(shmp->caller_info.head,shmp->caller_info.tail)>=
friendFamilyControl->friendFamilyPlan[plan_id].maxNumbers)
return 0;
}
if(flag == 0)
return 1;
if(friendFamilyControl->friendFamilyChangeChargeFlag)
{
if(GetFriendFamilyChangeCounter(shmp->caller_info.head,shmp->caller_info.tail)<=
friendFamilyControl->friendFamilyFreeChangeTimes)
return 1;
if(GetFavoriteNumberChangeCharge(shmp) > GetAccountBalance(shmp->caller_info.head,shmp->caller_info.tail))
{
return 0;
}
}
return 1;
}
int IsFavoriteNumberTypeOk(_state_data *shmp)
{
CosFriendFamilyControl *friendFamilyControl;
int cos_id;
char tmpChargeNumber[32];
cos_id = shmp->caller_info.cos_id;
friendFamilyControl = &ppsParam.ppsTables.cosTable[cos_id].friendFamilyControl[0];
strcpy(tmpChargeNumber,shmp->process_info.tmpDigits);
CutUnknownPrefix(tmpChargeNumber); //tariff prefix always be E.164
if(!GetMOTariffData(shmp,&shmp->process_info.tariff, tmpChargeNumber, shmp->caller_info.location))
return 0; //no tariff
switch(shmp->process_info.tariff.call_type)
{
case 0: //local
if(friendFamilyControl->friendFamilyNumberTypeLocal)
return 1;
break;
case 1: //NDD
if(friendFamilyControl->friendFamilyNumberTypeNDD)
return 1;
break;
case 2: //IDD
if(friendFamilyControl->friendFamilyNumberTypeIDD)
return 1;
break;
}
return 0;
}
int CheckClearFriendFamilyNumber(int head, int tail, int rent_charge,int rent_id)
{
int cos_id;
_prepaid_info *ptr;
CosFriendFamilyControl *friendFamilyControl;
PutLogFunID("CheckClearFriendFamilyNumber");
if(head>=MSISDN_HEAD_NUM || tail>=UNIT_STORE_ACCOUNT)
{
return 0;
}
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
//if(ptr->fav_change_counter==0)
// return 0;
ptr->free_favorite_call = 0;
ptr->free_favorite_sms = 0;
cos_id = ptr->cos_id;
friendFamilyControl = &ppsParam.ppsTables.cosTable[cos_id].friendFamilyControl[0];
if(friendFamilyControl->keepOrRemoveFriendFamilyNumber==0) //remove
{
ptr->rent_type ^= (0x01<<rent_id);
ptr->favorite_plan_id = 0;
ptr->favorite_numbers = 0;
ptr->favorite_plan_state = 0;
ptr->fav_change_counter = 0;
memset(ptr->favorite_number,0x00,MAX_FAVORITE_NUMBERS*MAX_MSISDN_BLEN);
if(ppsParam.ppsTables.cosTable[cos_id].smsNotificationInquiry[0].smsNotificationWhenFriendFamilyServiceRemoved )
sendPPSNotificationMessage(head, tail, SMS_FRIEND_FAMILY_REMOVE);
return 1;
}
if(friendFamilyControl->balanceThresholdToKeepFriendFamilyNumber!=0 &&
friendFamilyControl->balanceThresholdToKeepFriendFamilyNumber>GetAccountBalance( head, tail))
{
ptr->favorite_plan_state = 1;
if(ppsParam.ppsTables.cosTable[cos_id].smsNotificationInquiry[0].smsNotificationWhenFriendFamilyServiceSuspend)
sendPPSNotificationMessage(head, tail, SMS_FRIEND_FAMILY_SERVICE_SUSPEND);
return 1;
}
if(rent_charge>GetAccountBalance( head, tail))
{
ptr->favorite_plan_state = 1;
if(ppsParam.ppsTables.cosTable[cos_id].smsNotificationInquiry[0].smsNotificationWhenFriendFamilyServiceSuspend)
sendPPSNotificationMessage(head, tail, SMS_FRIEND_FAMILY_SERVICE_SUSPEND);
return 1;
}
return 0;
}
int CheckFriendFamilyPlanFreeCallOrSMS(int head, int tail, int type, int duration) /* type0=call, 1=sms */
{
/* when type0=call, check if call duration + existing free call duration exceeds threshold */
int cos_id, plan_id=0;
_prepaid_info *ptr;
CosFriendFamilyControl *friendFamilyControl;
PutLogFunID("CheckFriendFamilyPlanFreeSMS");
if(head>=MSISDN_HEAD_NUM || tail>=UNIT_STORE_ACCOUNT)
{
return 0;
}
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
if(ptr->favorite_numbers ==0)
return 0;
if(ptr->favorite_plan_id<=0 || ptr->favorite_plan_id>MAX_FAVORITE_PALN || ptr->favorite_plan_state !=0)
return 0;
plan_id = ptr->favorite_plan_id-1;
cos_id = ptr->cos_id;
friendFamilyControl = &ppsParam.ppsTables.cosTable[cos_id].friendFamilyControl[0];
switch(type)
{
case 0:
if(friendFamilyControl->friendFamilyPlan[plan_id].freeCallDuration == 0)
return 1;
if((ptr->free_favorite_call+duration) >= friendFamilyControl->friendFamilyPlan[plan_id].freeCallDuration*60) //keep
return 0;
break;
case 1:
default:
if(friendFamilyControl->friendFamilyPlan[plan_id].freeSMS == 0)
return 1;
if(ptr->free_favorite_sms >= friendFamilyControl->friendFamilyPlan[plan_id].freeSMS) //keep
return 0;
break;
}
return 1;
}
int IncreaseFriendFamilyFreeCallDuration(int head, int tail, int duration)
{
_prepaid_info *ptr;
PutLogFunID("IncreaseFriendFamilyFreeCallDuration");
if(head>=MSISDN_HEAD_NUM || tail>=UNIT_STORE_ACCOUNT)
{
return 0;
}
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
if(1)
{
int cos_id, max_free_duration, plan_id;
cos_id = ptr->cos_id;
plan_id = ptr->favorite_plan_id - 1;
if(plan_id>0 && plan_id<MAX_FAVORITE_PALN)
{
max_free_duration = ppsParam.ppsTables.cosTable[cos_id].friendFamilyControl[0].friendFamilyPlan[plan_id].freeCallDuration*60;
if(max_free_duration>0)
if((ptr->free_favorite_call + duration/CYCLE_STATE_INTERVAL)>max_free_duration)
{
sendPPSNotificationMessage(head, tail, SMS_FRIEND_FAMILY_PLAN_EXHAUST);
}
}
}
ptr->free_favorite_call += ceil( (double) duration / CYCLE_STATE_INTERVAL);
return 1;
}
int IncreaseFriendFamilyFreeSMSCounter(int head, int tail)
{
_prepaid_info *ptr;
PutLogFunID("IncreaseFriendFamilyFreeSMSCounter");
if(head>=MSISDN_HEAD_NUM || tail>=UNIT_STORE_ACCOUNT)
{
return 0;
}
ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
if(1)
{
int cos_id, max_free_sms, plan_id;
cos_id = ptr->cos_id;
plan_id = ptr->favorite_plan_id - 1;
if(plan_id>0 && plan_id<MAX_FAVORITE_PALN)
{
max_free_sms = ppsParam.ppsTables.cosTable[cos_id].friendFamilyControl[0].friendFamilyPlan[plan_id].freeSMS;
if(max_free_sms>0)
if((ptr->free_favorite_sms +1 )>max_free_sms)
{
sendPPSNotificationMessage(head, tail, SMS_FRIEND_FAMILY_PLAN_EXHAUST);
}
}
}
ptr->free_favorite_sms++;
return 1;
}
float GetSMSTariff(_state_data *shmp,u_char tariff_id)
{
int i,flag=0,len=0,maxlen=0,index=0;
float sms_fee = 0;
int discount=100;
_bill_sms *ptr;
char bill_no[64];
//tariff_id = shmp->caller_info.location;
//GetAccountZoneID(shmp->caller_info.head,shmp->caller_info.tail);
if(tariff_id>=MAX_ZONE_NUM ) tariff_id = 0;
if(shmp->process_info.mnp_status )
sprintf(bill_no,"%s%s",shmp->process_info.routing_number,
shmp->called_info.number);
else
strcpy(bill_no, (char *)shmp->charge_info.number);
for(i=1;i<MAX_SMS_PREFIX;i++)
{
ptr = &blf_shmp->bill_sms[tariff_id][i];
if(ptr->id !=0)
{
len = strlen(ptr->bill_id);
if(!strncasecmp(bill_no,ptr->bill_id,len))
if(len>maxlen)
{
maxlen = len;
flag = 1;
index = i;
}
}
}
if(flag == 0)
{
if(shmp->process_info.mnp_status )
{
if((logMsgFlag & 0x01) || shmp->process_info.logMsisdn)
{
DebugMsg(debugmib.display.asciiOut,
"\33[33m SMS to ported number, but no RN+MSISDN(%s) billing prefix\33[0m",
bill_no);
DebugMsg(debugmib.display.asciiOut,
"\33[33m Use dialing prefix %s as billing prefix\33[0m",
shmp->charge_info.number);
}
strcpy(bill_no, (char *)shmp->charge_info.number);
for(i=1;i<MAX_SMS_PREFIX;i++)
{
ptr = &blf_shmp->bill_sms[tariff_id][i];
if(ptr->id !=0)
{
len = strlen(ptr->bill_id);
if(!strncasecmp(bill_no,ptr->bill_id,len))
if(len>maxlen)
{
maxlen = len;
flag = 1;
index = i;
}
}
}
}
if(flag == 0)
ptr = &blf_shmp->bill_sms[tariff_id][DEFAULT_SMS_BILLING];
else
ptr = &blf_shmp->bill_sms[tariff_id][index];
}
else
{
ptr = &blf_shmp->bill_sms[tariff_id][index];
}
memcpy(&shmp->process_info.smsTariff,ptr,sizeof(_bill_sms));
sms_fee = ptr->base_fee;
discount = GetDiscount(tvnow.tv_sec,ptr->discountID);
// DebugMsg(debugmib.display.asciiOut,
// "sms tariff : fee:%0.4f discountID:%d discount: %d ",
// sms_fee,ptr->discountID,discount);
sms_fee = sms_fee * discount /100;
// if(!shmp->process_info.cap_flag)
shmp->process_info.cap_flag = ptr->cap_flag;
if(shmp->process_info.favoriteCall)
{
//COSTable *cosTableItem;
//cosTableItem = &ppsParam.ppsTables.cosTable[shmp->caller_info.cos_id];
if(CheckFriendFamilyPlanFreeCallOrSMS(shmp->caller_info.head, shmp->caller_info.tail, 1,0))
{
sms_fee = 0; /* free friend family SMS */
shmp->process_info.cap_flag = 0;
shmp->process_info.favoriteCall = FRIEND_FAMILY_FREE_SMS; /* free friend family call */
}
}
return sms_fee;
}
static void CheckCAPSMSNotification(_state_data *staPtr, _account_info *accountPtr, u_char cos_id,
int cap_type, float charge, int amount ) /* cap_type: 0=call, 1=sms */
{
int cap_plan,cap_seg, type,notifyFlag=0;
float c_threshold=0;
_prepaid_info *subPtr=NULL;
COSTable *cosTableItem;
CosCapPlan *capPlanPtr;
PutLogFunID("CheckCAPSMSNotification");
if(staPtr->process_info.cap_notify_flag) /* already send notification SM in this call */
return;
cap_plan = staPtr->process_info.cap_plan;
cap_seg = staPtr->process_info.cap_seg;
type = staPtr->process_info.cap_flag;
if(cap_seg>=3) return; /* reach the last CAP segment */
subPtr = &ramshm_ptr->prepaid_data.prepaid_info[accountPtr->head][accountPtr->tail];
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
capPlanPtr = &cosTableItem->capPlan[cap_plan];
if(cap_seg == 0)
c_threshold = (float)capPlanPtr->threshold0;
else if(cap_seg == 1)
c_threshold = (float)capPlanPtr->threshold1;
else if(cap_seg == 2)
c_threshold = (float)capPlanPtr->threshold2;
switch(cap_type)
{
case 0:
if(capPlanPtr->type == 0) //counter
{
if(type == 1) /* in net call */
{
if((subPtr->in_net_cap_call_duration + amount)>=c_threshold)
notifyFlag = 1;
}
else if(type == 2) /* out net call */
{
if((subPtr->out_net_cap_call_duration + amount)>=c_threshold)
notifyFlag = 1;
}
}
else if(charge>0) //balance
{
if(type == 1)
{
if((subPtr->in_net_cap_call_balance + charge)>=c_threshold)
notifyFlag = 1;
}
else if(type == 2)
{
if((subPtr->out_net_cap_call_balance + charge)>=c_threshold)
notifyFlag = 1;
}
}
break;
case 1:
if(capPlanPtr->type == 0) //counter
{
if(type == 1)
{
if((subPtr->in_net_cap_sms_counter + 1)==c_threshold)
notifyFlag = 1;
}
else if(type == 2)
{
if((subPtr->out_net_cap_sms_counter + 1)==c_threshold)
notifyFlag = 1;
}
}
else if(charge>0) //balance
{
if(type == 1)
{
if((subPtr->in_net_cap_sms_balance + charge)>=c_threshold)
notifyFlag = 1;
}
else if(type == 2)
{
if((subPtr->out_net_cap_sms_balance + charge)>=c_threshold)
notifyFlag = 1;
}
}
break;
}
if(notifyFlag)
{
if(cap_seg == 0)
PPSSendUserSMSNotification(accountPtr->head, accountPtr->tail, (char *)getSmsSentenceNative(0,SMS_CAPSMS_NOTIFY));
else if(cap_seg == 1)
PPSSendUserSMSNotification(accountPtr->head, accountPtr->tail, (char *)getSmsSentenceNative(0,SMS_CAPSMS_1_NOTIFY));
else
{PPSSendUserSMSNotification(accountPtr->head, accountPtr->tail, (char *)getSmsSentenceNative(0,SMS_CAPSMS_2_NOTIFY));}
staPtr->process_info.cap_notify_flag = 1;
}
}
void UpdateSubsCapInfo(_account_info *ptr, int cap_type,float charge, int amount, _state_data *sta_ptr)
{
/* cap type: 0=call, 1=sm */
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
_prepaid_info *subPtr;
u_char cos_id;
int type=sta_ptr->process_info.cap_flag;
COSTable *cosTableItem;
PutLogFunID("UpdateSubsCapBalance");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
subPtr = &shmp->prepaid_info[ptr->head][ptr->tail];
cos_id = subPtr->cos_id%MaxCosTableItem;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
if(cosTableItem->smsNotificationInquiry[0].smsNotificationWhenCapPlanChanged)
{
CheckCAPSMSNotification(sta_ptr,ptr,cos_id,cap_type,charge, amount);
}
if(cap_type==0)
{
if(type == 1)
{
subPtr->in_net_cap_call_balance =
subPtr->in_net_cap_call_balance + charge;
subPtr->in_net_cap_call_duration += amount;
subPtr->in_net_cap_balance =
subPtr->in_net_cap_balance + charge;
}
else if(type == 2)
{
subPtr->out_net_cap_call_balance =
subPtr->out_net_cap_call_balance + charge;
subPtr->out_net_cap_call_duration += amount;
subPtr->out_net_cap_balance =
subPtr->out_net_cap_balance + charge;
}
}
else
{
if(type == 1)
{
subPtr->in_net_cap_sms_balance =
subPtr->in_net_cap_sms_balance + charge;
subPtr->in_net_cap_sms_counter ++;
subPtr->in_net_cap_balance =
subPtr->in_net_cap_balance + charge;
}
else if(type == 2)
{
subPtr->out_net_cap_sms_balance =
subPtr->out_net_cap_sms_balance + charge;
subPtr->out_net_cap_sms_counter ++;
subPtr->out_net_cap_balance =
subPtr->out_net_cap_balance + charge;
}
}
}
}
void GetSubsCapInfo(_account_info *ptr,int cap_type, float *balance, int *counter, int type, int cap_flag)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetSubsCapInfo");
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
if(cap_flag == CAP_TYPE_BOTH)
{
if(type == 0)
{
*balance = shmp->prepaid_info[ptr->head][ptr->tail].in_net_cap_balance;
*counter = 0;
}
else
{
*balance = shmp->prepaid_info[ptr->head][ptr->tail].out_net_cap_balance;
*counter = 0;
}
return;
}
if(cap_type==0)
{
if(type==0) /* int net */
{
*balance = shmp->prepaid_info[ptr->head][ptr->tail].in_net_cap_call_balance;
*counter = shmp->prepaid_info[ptr->head][ptr->tail].in_net_cap_call_duration;
}
else /* out net */
{
*balance = shmp->prepaid_info[ptr->head][ptr->tail].out_net_cap_call_balance;
*counter = shmp->prepaid_info[ptr->head][ptr->tail].out_net_cap_call_duration;
}
}
else
{
if(type==0) /* int net */
{
*balance = shmp->prepaid_info[ptr->head][ptr->tail].in_net_cap_sms_balance;
*counter = shmp->prepaid_info[ptr->head][ptr->tail].in_net_cap_sms_counter;
}
else /* out net */
{
*balance = shmp->prepaid_info[ptr->head][ptr->tail].out_net_cap_sms_balance;
*counter = shmp->prepaid_info[ptr->head][ptr->tail].out_net_cap_sms_counter;
}
}
}
else
{
*balance = 0;
*counter = 0;
}
}
int GetSubsCapTariffID(_state_data *shmp, int call_type)
{
int cos_id=0,tariff_id=-1,cap_plan=0,loop=0;
float cap_balance;
int cap_counter;
float c_threshold0=0,c_threshold1=0,c_threshold2=0;
int cap_flag,cap_type;
COSTable *cosTableItem;
CosCapPlan *capPlanPtr;
PutLogFunID("GetSubsCapTariffID");
cos_id = shmp->caller_info.cos_id%MaxCosTableItem;
if(call_type == 0) /* call */
{
cap_type = 1; /* call */
cap_flag = 1;
}
else /* sm , please refer param.h cap_plan for the assignment*/
{
cap_type = 2;
cap_flag = 2;
}
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
for(loop=0;loop<MaxcapPlanTableItem;loop++)
{
if((cosTableItem->capPlan[loop].flag & cap_flag )== cap_type && //call
shmp->process_info.cap_flag == (loop%2+1) )
{
cap_flag = cosTableItem->capPlan[loop].flag; /* 0=disable, 1/2/3=cap by SM/CALL/BOTH */
cap_plan = loop;
break;
}
}
shmp->process_info.cap_plan = cap_plan;
GetSubsCapInfo(&shmp->caller_info,
call_type, // call=0 or sm=1
&cap_balance,
&cap_counter,
shmp->process_info.cap_flag-1, //innet=0, outnet=1
cap_flag
);
capPlanPtr = &cosTableItem->capPlan[cap_plan];
c_threshold0 = (float)capPlanPtr->threshold0;
c_threshold1 = (float)capPlanPtr->threshold1;
c_threshold2 = (float)capPlanPtr->threshold2;
if(capPlanPtr->type == 0)
{
if(c_threshold0>0)
{
if(cap_counter<c_threshold0)
{
tariff_id = capPlanPtr->tariffID0;
shmp->process_info.cap_seg = 0;
}
else if(c_threshold1>0)
{
if(cap_counter<c_threshold1)
{
tariff_id = capPlanPtr->tariffID1;
shmp->process_info.cap_seg = 1;
}
else if(c_threshold2>0)
{
if(cap_counter<c_threshold2)
{
tariff_id = capPlanPtr->tariffID2;
shmp->process_info.cap_seg = 2;
}
else
{
tariff_id = capPlanPtr->tariffID3;
shmp->process_info.cap_seg = 3;
}
}
else
{
tariff_id = capPlanPtr->tariffID2;
shmp->process_info.cap_seg = 2;
}
}
else
{
tariff_id = capPlanPtr->tariffID1;
shmp->process_info.cap_seg = 1;
}
}
}
else
{
if(c_threshold0>0)
{
if(cap_balance<c_threshold0)
{
tariff_id = capPlanPtr->tariffID0;
shmp->process_info.cap_seg = 0;
}
else if(c_threshold1>0)
{
if(cap_balance<c_threshold1)
{
tariff_id = capPlanPtr->tariffID1;
shmp->process_info.cap_seg = 1;
}
else if(c_threshold2>0)
{
if(cap_balance<c_threshold2)
{
tariff_id = capPlanPtr->tariffID2;
shmp->process_info.cap_seg = 2;
}
else
{
tariff_id = capPlanPtr->tariffID3;
shmp->process_info.cap_seg = 3;
}
}
else
{
tariff_id = capPlanPtr->tariffID2;
shmp->process_info.cap_seg = 2;
}
}
else
{
tariff_id = capPlanPtr->tariffID1;
shmp->process_info.cap_seg = 1;
}
}
}
return tariff_id;
}
int UpdateAccountBundlePlanInfoWarningFlag(_state_data *shmp, int flag)
{
_prepaid_data *ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
PutLogFunID("UpdateAccountBundlePlanInfoWarningFlag");
head = shmp->caller_info.head;
tail = shmp->caller_info.tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &ptr->prepaid_info[head][tail];
sub_ptr->bundle_info.warning_sms_flag = flag;
}
return 1;
}
int UpdateAccountBundlePlanInfo(_account_info *shmp, long set_value[7])
{
_prepaid_data *ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
PutLogFunID("UpdateAccountBundlePlanInfo");
head = shmp->head;
tail = shmp->tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &ptr->prepaid_info[head][tail];
if(sub_ptr->bundle_info.data == 0)// set voice/sms to 0, if data==0 when subscribe bundle
{
sub_ptr->bundle_info.validity_date = tvnow.tv_sec - 1000;
sub_ptr->bundle_info.mo_voice = 0;
sub_ptr->bundle_info.mt_voice = 0;
sub_ptr->bundle_info.sms = 0;
}
//sub_ptr->balance = sub_ptr->balance + set_value[0];
sub_ptr->bundle_info.data += ( set_value[1] * 1024 * 1024);
sub_ptr->bundle_info.mo_voice += ( set_value[2] * 60 );
sub_ptr->bundle_info.mt_voice += ( set_value[3] * 60 );
sub_ptr->bundle_info.sms += set_value[4];
sub_ptr->bundle_info.warning_sms_flag = set_value[6];
if(sub_ptr->bundle_info.validity_date < tvnow.tv_sec)
{
sub_ptr->bundle_info.validity_date = tvnow.tv_sec + set_value[5] * 24 * 3600;
}
else
{
sub_ptr->bundle_info.validity_date += set_value[5] * 24 * 3600;
}
}
return 1;
}
int GetAccountBundlePlanInfo(_account_info *ptr, long ret_value[6])
{
_prepaid_data *data_ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
int retval = 0;
int bundle_info_updated_flag = 1;
PutLogFunID("GetAccountBundlePlanInfo");
head = ptr->head;
tail = ptr->tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &data_ptr->prepaid_info[head][tail];
// see if we have to set bundle to 0===================================
if ((sub_ptr->bundle_info.validity_date > 0) && (sub_ptr->bundle_info.validity_date < tvnow.tv_sec))// 1) set bundle to 0, if expired when querying.
{
memset(&sub_ptr->bundle_info, 0x00, sizeof(_bundle_info));
}
else if (((sub_ptr->bundle_info.validity_date >= tvnow.tv_sec) && (sub_ptr->bundle_info.data <= 0))\
|| ((sub_ptr->bundle_info.validity_date == 0) && (sub_ptr->bundle_info.data > 0)))// 2) set bundle to 0, if data == 0 and not expired
// && sub_ptr->bundle_info.mo_voice == 0
// && sub_ptr->bundle_info.mt_voice == 0
// && sub_ptr->bundle_info.sms == 0)
{
memset(&sub_ptr->bundle_info, 0x00, sizeof(_bundle_info));
}
else
{
bundle_info_updated_flag = 0;// no change, so do not have to sync.
}
//=====================================================
// return bundle when data > 0 and not expired.
if ((sub_ptr->bundle_info.data > 0) && (sub_ptr->bundle_info.validity_date >= tvnow.tv_sec))
{
retval = 1;
}
//
ret_value[0] = (sub_ptr->bundle_info.data /( 1024*1024));
ret_value[1] = (sub_ptr->bundle_info.mo_voice / 60 );
ret_value[2] = (sub_ptr->bundle_info.mt_voice / 60 );
ret_value[3] = ( sub_ptr->bundle_info.sms );
ret_value[4] = sub_ptr->bundle_info.validity_date;
ret_value[5] = sub_ptr->bundle_info.warning_sms_flag;
}
if(bundle_info_updated_flag )
{
SendAccountRealSync_2(ptr,0.0,0.0,OMC_OCODE_EDIT);
}
return retval;
}
extern void pps_print_event(u_char logMsisdnFlag,const char *fmt, ...);
long long pps_get_account_bundle_data(_state_data *shmp)// get remained Bytes from user bundle info
{
_prepaid_data *data_ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
PutLogFunID("pps_get_account_bundle_data");
head = shmp->caller_info.head;
tail = shmp->caller_info.tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &data_ptr->prepaid_info[head][tail];
/*
pps_print_event(shmp->process_info.logMsisdn,"[%04d] %s, bundle data=%lld, validity=%ld, now time=%ld",
shmp->process_info.portid,
__FUNCTION__,
sub_ptr->bundle_info.data,
sub_ptr->bundle_info.validity_date,
tvnow.tv_sec);
*/
if(sub_ptr->bundle_info.validity_date > tvnow.tv_sec)
{
return sub_ptr->bundle_info.data;
}
else
{
return 0;
}
}
return 0;
}
int pps_get_account_bundle_mo_voice(_state_data *shmp)// get remained Bytes from user bundle info
{
_prepaid_data *data_ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
PutLogFunID("pps_get_account_bundle_mo_voice");
head = shmp->caller_info.head;
tail = shmp->caller_info.tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &data_ptr->prepaid_info[head][tail];
if(sub_ptr->bundle_info.validity_date > tvnow.tv_sec)
{
return sub_ptr->bundle_info.mo_voice;
}
else
{
return 0;
}
}
return 0;
}
int pps_update_account_bundle_mo_voice(_state_data *shmp, int seconds)//
{
_prepaid_data *data_ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
PutLogFunID("pps_update_account_bundle_mo_voice");
head = shmp->caller_info.head;
tail = shmp->caller_info.tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &data_ptr->prepaid_info[head][tail];
if(sub_ptr->bundle_info.validity_date > tvnow.tv_sec)
{
sub_ptr->bundle_info.mo_voice += seconds;
if(sub_ptr->bundle_info.mo_voice <= 0)
{
sub_ptr->bundle_info.mo_voice = 0;
subscribe_bundle_plan_send_used_up_info((char *)shmp->caller_info.number, SMS_BUNDLE_PLAN_VOICE_USEDUP); /* should only send MO voice is used up */
}
}
else
{
return 0;
}
}
return 1;
}
int pps_get_account_bundle_mt_voice(_state_data *shmp)//
{
_prepaid_data *data_ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
PutLogFunID("pps_get_account_bundle_mt_voice");
head = shmp->called_info.head;
tail = shmp->called_info.tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &data_ptr->prepaid_info[head][tail];
if(sub_ptr->bundle_info.validity_date > tvnow.tv_sec)
{
return sub_ptr->bundle_info.mo_voice;// mt use the same bundle as mo
}
else
{
return 0;
}
}
return 0;
}
int pps_update_account_bundle_mt_voice(_state_data *shmp, int seconds)//
{
_prepaid_data *data_ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
PutLogFunID("pps_update_account_bundle_mt_voice");
head = shmp->called_info.head;
tail = shmp->called_info.tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &data_ptr->prepaid_info[head][tail];
if(sub_ptr->bundle_info.validity_date > tvnow.tv_sec)
{
sub_ptr->bundle_info.mo_voice += seconds;// mt use the same bundle as mo
if(sub_ptr->bundle_info.mo_voice <= 0)
{
sub_ptr->bundle_info.mo_voice = 0;
subscribe_bundle_plan_send_used_up_info((char *)shmp->called_info.number, SMS_BUNDLE_PLAN_VOICE_USEDUP); /* should only send MT voice is used up */
}
}
else
{
return 0;
}
}
return 1;
}
int pps_get_account_bundle_mo_sms(_state_data *shmp)// get remained Bytes from user bundle info
{
_prepaid_data *data_ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
PutLogFunID("pps_get_account_bundle_mo_sms");
head = shmp->caller_info.head;
tail = shmp->caller_info.tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &data_ptr->prepaid_info[head][tail];
if(sub_ptr->bundle_info.validity_date > tvnow.tv_sec)
{
return sub_ptr->bundle_info.sms;
}
else
{
return 0;
}
}
return 0;
}
int pps_update_account_bundle_mo_sms(_state_data *shmp, int count)// get remained Bytes from user bundle info
{
_prepaid_data *data_ptr =&ramshm_ptr->prepaid_data;
_prepaid_info *sub_ptr = NULL;
int head, tail;
PutLogFunID("pps_get_account_bundle_mo_voice");
head = shmp->caller_info.head;
tail = shmp->caller_info.tail;
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
sub_ptr = &data_ptr->prepaid_info[head][tail];
// if(sub_ptr->bundle_info.validity_date > tvnow.tv_sec)
{
sub_ptr->bundle_info.sms += count;
if(sub_ptr->bundle_info.sms <= 0)
{
sub_ptr->bundle_info.sms = 0;
subscribe_bundle_plan_send_used_up_info((char *)shmp->caller_info.number, SMS_BUNDLE_PLAN_SMS_USEDUP); /* should only send MO SMS is used up */
}
}
/*
else
{
return 0;
}
*/
}
return 1;
}
extern int ocs_get_charge_prefix(char *dialed_number, char *prefix, char *area_name, int *call_type);
extern int crm_check_if_cug_call(_account_info *caller, _account_info *called);
int BillingSMSProc(_state_data *shmp, int sms_num)
{
float balance = 0, discount=100.0;
float mosms_unit_charge ;
int cos_id,tariff_id;
COSTable *cosTableItem = NULL;
int charge_num = sms_num, bundle_used_num = 0;
CosServiceControl *serviceControlItem = NULL;
PutLogFunID("BillingSMSProc");
if(OCS_with_external_CRM())
{
if(crm_check_if_cug_call(&shmp->caller_info, &shmp->called_info))
{
mosms_unit_charge = 0;
shmp->process_info.rest_if.total_plan_value = 0;
shmp->process_info.rest_if.used_plan_value = 0;
}
else
mosms_unit_charge = shmp->process_info.rest_if.unit_charge * shmp->process_info.rest_if.tariff_discount / discount;
}
else
mosms_unit_charge = GetSMSTariff(shmp,shmp->caller_info.location);
// Check Cap or Bundle is used================================
cos_id = shmp->caller_info.cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
serviceControlItem = &cosTableItem->serviceControl[0];
if(serviceControlItem->cap_or_bundle_in_tariff)// bundle is used, so we can set bundle flag and clear cap flag
{
shmp->process_info.bundle_flag = shmp->process_info.cap_flag;
shmp->process_info.cap_flag = 0;
}
//==================================================
if(shmp->process_info.bundle_flag)
{
int left_mo_sms = 0;
left_mo_sms = pps_get_account_bundle_mo_sms(shmp);
if(left_mo_sms > 0)
{
if (left_mo_sms >= charge_num)
{
shmp->caller_info.fee = 0;
shmp->caller_info.valid_time = 10*ONE_MINUTE_STATE_TIME;
shmp->called_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
bundle_used_num = charge_num;
return bundle_used_num;// bundle charge num
}
else
{
charge_num -= left_mo_sms;
bundle_used_num = left_mo_sms;
}
}
else
{
shmp->process_info.bundle_flag = 0;
}
}
if(shmp->process_info.cap_flag)
{
tariff_id=GetSubsCapTariffID(shmp,CAP_SMS);
if(tariff_id>=0)
{
mosms_unit_charge = GetSMSTariff(shmp,tariff_id);
/* there should always be DEFAULT tariff prefix */
shmp->caller_info.location = tariff_id;
}
}
//no roaming fee charged for ROAMING SMS, 2005-05-09
switch(shmp->process_info.call_type)
{
case CT_MO_SM:
if(shmp->process_info.serviceType == SRV_SCRATCH_CARD_RECHARGE ||
shmp->process_info.serviceType == SRV_RECHARGE_2TYPES ||
shmp->process_info.serviceType == SRV_FEE_TRANSFER ||
shmp->process_info.serviceType == SRV_FREE_SMS ||
shmp->process_info.serviceType == SRV_CALL_ME_BACK ||
shmp->process_info.serviceType == SRV_BUNDLE_PLAN ||
shmp->process_info.serviceType == USSD_OC_BUNDLE_QUERY)
{
shmp->process_info.cap_flag = 0;
shmp->caller_info.fee = 0;
shmp->caller_info.valid_time = 10*ONE_MINUTE_STATE_TIME;
shmp->called_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
return bundle_used_num;
}
if(cosTableItem->serviceControl[0].moThresholdSet)
{
balance = (int)GetBalanceWithPromotionControl(shmp,&shmp->caller_info)
+ GetOverdraft(&shmp->caller_info)
- (cosTableItem->serviceControl[0].moMinimumBalance);
if(balance<0)
{
shmp->caller_info.fee = 0;
shmp->caller_info.valid_time = 0;
shmp->called_info.fee = 0;
shmp->called_info.valid_time = 0;
return bundle_used_num;
}
}
balance = GetBalanceWithPromotionControl(shmp,&shmp->caller_info) + GetOverdraft(&shmp->caller_info);
if(shmp->process_info.serviceType == SRV_INQUIRY )
{
shmp->process_info.cap_flag = 0;
if(!(cosTableItem->smsNotificationInquiry[0].chargeWhenInquiryBySMS))
{ /* not charging on SM inquring */
shmp->caller_info.fee = 0;
shmp->caller_info.valid_time = 10*ONE_MINUTE_STATE_TIME;
/* should be a parameter */
shmp->called_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
return bundle_used_num;
}
else
{
/* inquiry charged, recharge should be always free,not yet,2004-01-06 */
if(IncreaseServiceSM(shmp->caller_info.head,
shmp->caller_info.tail)<=
(cosTableItem->smsNotificationInquiry[0].freeInquiryPerDay))
{
shmp->caller_info.fee = 0;
shmp->caller_info.valid_time = 10*ONE_MINUTE_STATE_TIME;
shmp->called_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
return bundle_used_num;
}
}
}
/* zero balance can't send free sms,06-02-27 */
/*
if(balance == 0 && mosms_unit_charge==0)
{
shmp->caller_info.valid_time = 0; // should be a parameter
shmp->called_info.valid_time = 0;
shmp->process_info.tcos = CALLER_CREDIT_OUT; // no enough balance
}
else if(balance>=mosms_unit_charge)
*/
if(balance>=(mosms_unit_charge * charge_num))
{
shmp->caller_info.valid_time = 10*ONE_MINUTE_STATE_TIME; /* should be a parameter */
shmp->called_info.valid_time = 10*ONE_MINUTE_STATE_TIME;
shmp->caller_info.fee = mosms_unit_charge * charge_num;
shmp->called_info.fee = 0x00;
}
else
{
shmp->caller_info.valid_time = 0; /* should be a parameter */
shmp->called_info.valid_time = 0;
shmp->process_info.tcos = CALLER_CREDIT_OUT; /* no enough balance */
}
break;
default:
shmp->caller_info.valid_time = 0;
shmp->called_info.valid_time = 0;
shmp->process_info.tcos = CALLER_CREDIT_OUT;
break;
}
return bundle_used_num;
}
int
ConferenceCallBillingProc(_state_data *shmp,int duration)
{
float charge,balance;
int unit_time=60,unit_amount,tariff_id=0;
int cos_id;
COSTable *cosTableItem;
PutLogFunID("ConferenceCallBillingProc");
tariff_id = GetAccountZoneID(shmp->caller_info.head,shmp->caller_info.tail);
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
if(shmp->caller_info.status != T_NORMAL ||
tvnow.tv_sec>= GetExpiration(&shmp->caller_info))
return FALSE;
cos_id = shmp->caller_info.cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
unit_time = blf_shmp->comm_tariff[tariff_id].ccChargeUnit;
if(unit_time<=0) unit_time = 60;
unit_amount = blf_shmp->comm_tariff[tariff_id].ccChargeAmount;
if(unit_amount<=0) unit_amount = 20;
if(cosTableItem->serviceControl[0].moThresholdSet)
balance = GetBalanceWithPromotionControl(shmp,&shmp->caller_info) + GetOverdraft(&shmp->caller_info)
- cosTableItem->serviceControl[0].moMinimumBalance;
if(balance<0)
{
return FALSE;
}
balance = GetBalanceWithPromotionControl(shmp,&shmp->caller_info) + GetOverdraft(&shmp->caller_info);
charge = (duration * unit_amount*1.0) / unit_time;
shmp->caller_info.charge = charge;
shmp->caller_info.fee = charge;
if(balance>=charge) return TRUE;
return FALSE;
}
void ChangeTariffToCugTariff(_state_data *shmp,_bill_tariff *ptar){
u_short rUnit=60;
float rAmount=0;
u_short Unit=0;
u_char tier;
int tariff_id;
PutLogFunID("ChangeTariffToCugTariff");
tariff_id = shmp->caller_info.location;
Unit = ptar->unit_time;
if(Unit == 0) Unit = 60;
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
rUnit = blf_shmp->comm_tariff[tariff_id].cugChargeUnit;
rAmount = blf_shmp->comm_tariff[tariff_id].cugChargeAmount;
if(rUnit == 0) rUnit = 60;
tier = getCurrentTier(shmp,ptar);
ptar->tierRating.rating[tier].base_fee = Unit * rAmount /rUnit;
}
void ChangeTariffToFavoriteCallTariff(_state_data *shmp,_bill_tariff *ptar)
{
u_short rUnit=60;
float rAmount=0;
u_short Unit=0;
u_char tier;
int tariff_id;
PutLogFunID("ChangeTariffToFavoriteCallTariff");
if(shmp->process_info.favoriteCall == FRIEND_FAMILY_FREE_CALL)
return;
tariff_id = shmp->caller_info.location;
Unit = ptar->unit_time;
if(Unit == 0) Unit = 60;
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
rUnit = blf_shmp->comm_tariff[tariff_id].favChargeUnit;
rAmount = blf_shmp->comm_tariff[tariff_id].favChargeAmount;
if(rUnit ==0) rUnit = 60;
tier = getCurrentTier(shmp,ptar);
ptar->tierRating.rating[tier].base_fee = Unit * rAmount /rUnit;
}
void ChangeTariffToMORoamingTariff(_state_data *shmp,_bill_tariff *ptar){
u_short rUnit,Unit=0;
float rAmount,Amount=0;
u_char tier;
int tariff_id;
_bill_tariff const *moPtr;
PutLogFunID("ChangeTariffToMORoamingTariff");
moPtr = shmp->process_info.tariffMoReadOnly;
if(moPtr == NULL)
{
pps_print_error(shmp->process_info.logMsisdn,"[%05d]ChangeTariffToMORoamingTariff,no mo tariff",
shmp->process_info.portid);
return;
}
tariff_id = shmp->caller_info.location;
Unit = moPtr->unit_time;
if(Unit == 0) Unit = 60;
tier = getCurrentTier(shmp, (_bill_tariff *)moPtr);
Amount = moPtr->tierRating.rating[tier].base_fee;
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
rUnit = blf_shmp->comm_tariff[tariff_id].roamingChargeUnit;
rAmount = blf_shmp->comm_tariff[tariff_id].roamingChargeAmount;
if(rUnit ==0) rUnit = 60;
ptar->tierRating.rating[tier].base_fee = Unit * rAmount /rUnit + Amount;
}
void ChangeTariffToMTRoamingTariff(_state_data *shmp,_bill_tariff *ptar)
{
u_short rUnit,Unit;
float rAmount,base_fee;
int location;
char destination[128],inter_prefix[32];
u_char tier,tierDest;
_bill_tariff *ptrTemp,btar;
_bill_tariff const *mtPtr;
PutLogFunID("ChangeTariffToMTRoamingTariff");
memset(&btar,0,sizeof(_bill_tariff));
ptrTemp = &btar;
mtPtr = shmp->process_info.tariffMtReadOnly;
if(mtPtr == NULL)
{
pps_print_error(shmp->process_info.logMsisdn,"[%05d]ChangeTariffToMTRoamingTariff,no mt tariff",
shmp->process_info.portid);
return;
}
location = GetAccountZoneID(shmp->called_info.head,
shmp->called_info.tail);
xap_get_interprefix((u8 *)inter_prefix);
BcdToAscii(destination, (BYTE *)inter_prefix, 4);
StringCut(destination,'E');
strcat(destination,shmp->cdr_info.locationNumber);
shmp->process_info.tariff_flag = GetMOTariffData(shmp,ptrTemp, destination, location);
if(shmp->process_info.tariff_flag <= 0)
{
pps_print_error(shmp->process_info.logMsisdn,"[%05d]ChangeTariffToMTRoamingTariff,can't find prefix by:%s,assume basic fee and long fee as 0",
shmp->process_info.portid,destination);
}
location = shmp->called_info.location;
rUnit = blf_shmp->comm_tariff[location].roamingChargeUnit;
rAmount = blf_shmp->comm_tariff[location].roamingChargeAmount;
if(rUnit ==0) rUnit = 60;
Unit = mtPtr->unit_time;
if(Unit == 0) Unit = 60;
tier = getCurrentTier(shmp, (_bill_tariff *)mtPtr);
tierDest = getCurrentTier(shmp,ptrTemp);
base_fee = mtPtr->tierRating.rating[tier].base_fee;
ptar->tierRating.rating[tier].base_fee = base_fee + Unit * rAmount /rUnit;
Unit = ptrTemp->unit_time;
if(Unit == 0) Unit = 60;
rUnit = mtPtr->unit_time;
if(rUnit == 0) rUnit = 60;
if(Unit<rUnit)
{
ptar->tierRating.rating[tier].long_distance_fee =
mtPtr->tierRating.rating[tier].long_distance_fee + ptrTemp->tierRating.rating[tierDest].long_distance_fee*rUnit/Unit;
}
else
{
ptar->tierRating.rating[tier].long_distance_fee =
ptrTemp->tierRating.rating[tierDest].long_distance_fee + mtPtr->tierRating.rating[tier].long_distance_fee * Unit / rUnit;
ptar->tierRating.rating[tier].base_fee = ptar->tierRating.rating[tier].base_fee * Unit / rUnit;
ptar->adjustment = mtPtr->adjustment * Unit / rUnit;
ptar->unit_time = mtPtr->unit_time * Unit / rUnit;
ptar->mini_unit = ptrTemp->mini_unit;
}
}
void ChangeTariffToCfTariff(_state_data *shmp,_bill_tariff *ptar){
u_short cfUnit;
float cfAmount;
u_short Unit=0;
u_char tier;
int tariff_id;
PutLogFunID("ChangeTariffToCfTariff");
tariff_id = shmp->caller_info.location;
Unit = ptar->unit_time;
if(Unit == 0) Unit = 60;
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
cfUnit = blf_shmp->comm_tariff[tariff_id].cfChargeUnit;
cfAmount = blf_shmp->comm_tariff[tariff_id].cfChargeAmount;
if(cfUnit ==0) cfUnit = 60;
tier = getCurrentTier(shmp,ptar);
ptar->tierRating.rating[tier].base_fee = Unit * cfAmount /cfUnit;
}
void ChangeTariffToCfCugTariff(_state_data *shmp,_bill_tariff *ptar){
u_short cfUnit;
float cfAmount;
u_short Unit=0;
u_char tier;
int tariff_id;
PutLogFunID("ChangeTariffToCfCugTariff");
tariff_id = shmp->caller_info.location;
Unit = ptar->unit_time;
if(Unit == 0) Unit = 60;
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
cfUnit = blf_shmp->comm_tariff[tariff_id].cf_cugChargeUnit;
cfAmount = blf_shmp->comm_tariff[tariff_id].cf_cugChargeAmount;
if(cfUnit ==0) cfUnit = 60;
tier = getCurrentTier(shmp,ptar);
ptar->tierRating.rating[tier].base_fee = Unit * cfAmount /cfUnit;
}
void ChangeTariffToCfFavTariff(_state_data *shmp,_bill_tariff *ptar){
u_short cfUnit;
float cfAmount;
u_short Unit=0;
u_char tier;
int tariff_id;
PutLogFunID("ChangeTariffToCfFavTariff");
tariff_id = shmp->caller_info.location;
Unit = ptar->unit_time;
if(Unit == 0) Unit = 60;
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
cfUnit = blf_shmp->comm_tariff[tariff_id].cf_favChargeUnit;
cfAmount = blf_shmp->comm_tariff[tariff_id].cf_favChargeAmount;
if(cfUnit ==0) cfUnit = 60;
tier = getCurrentTier(shmp,ptar);
ptar->tierRating.rating[tier].base_fee = Unit * cfAmount /cfUnit;
}
void ChangeTariffToCugFavTariff(_state_data *shmp,_bill_tariff *ptar){
u_short cfUnit;
float cfAmount;
u_short Unit=0;
u_char tier;
int tariff_id;
PutLogFunID("ChangeTariffToCugFavTariff");
tariff_id = shmp->caller_info.location;
Unit = ptar->unit_time;
if(Unit == 0) Unit = 60;
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
cfUnit = blf_shmp->comm_tariff[tariff_id].cug_favChargeUnit;
cfAmount = blf_shmp->comm_tariff[tariff_id].cug_favChargeAmount;
if(cfUnit ==0) cfUnit = 60;
tier = getCurrentTier(shmp,ptar);
ptar->tierRating.rating[tier].base_fee = Unit * cfAmount /cfUnit;
}
void ChangeTariffToCfCugFavTariff(_state_data *shmp,_bill_tariff *ptar){
u_short cfUnit;
float cfAmount;
u_short Unit=0;
u_char tier;
int tariff_id;
PutLogFunID("ChangeTariffToCfCugFavTariff");
tariff_id = shmp->caller_info.location;
Unit = ptar->unit_time;
if(Unit == 0) Unit = 60;
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
cfUnit = blf_shmp->comm_tariff[tariff_id].cf_cug_favChargeUnit;
cfAmount = blf_shmp->comm_tariff[tariff_id].cf_cug_favChargeAmount;
if(cfUnit ==0) cfUnit = 60;
tier = getCurrentTier(shmp,ptar);
ptar->tierRating.rating[tier].base_fee = Unit * cfAmount /cfUnit;
}
int GetMTTariffData(_state_data *shmp,
u_char tariffID,
_bill_tariff *ptar,
_account_info *pinfo,
_account_info *pcaller)
{
int prefixIndex = DEFAULT_MT_BILLING,i;
int len=0,maxlen=0;
_bill_tariff *ptr;
int cos_id;
COSTable *cosTableItem;
PutLogFunID("GetMTTariffData");
cos_id = pinfo->cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
if(cosTableItem->serviceControl[0].mtChargeFlag==0)
{
ptar->call_type = 4;
ptar->free_time = 0;
ptar->unit_time = 60;
ptar->mini_unit = 1;
ptar->adjustment = 0;
memset(&ptar->tierRating,0,sizeof(TIER_RATING));
return 1;
}
if(tariffID>=MAX_ZONE_NUM )
tariffID = 0;
memset(ptar,0,sizeof(_bill_tariff));
for(i=1;i<CALLED_BASE_NUM;i++)
{
ptr = &blf_shmp->called_tariff[tariffID][i];
if(ptr->bill_id[0] == 0) continue;
len = strlen(ptr->bill_id);
if(len>maxlen)
if(!strncasecmp((char *)pcaller->number,ptr->bill_id,len))
{
maxlen = len;
prefixIndex = i;
}
}
memcpy(ptar,&blf_shmp->called_tariff[tariffID][prefixIndex],sizeof(_bill_tariff));
shmp->process_info.tariffMtReadOnly = &blf_shmp->called_tariff[tariffID][prefixIndex];
return 1;
}
int cfLargeThancug(int tariff_id)
{
_comm_tariff *commTariff;
PutLogFunID("cfLargeThancug");
if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) tariff_id = 0;
commTariff = &ramshm_ptr->tariff_data.comm_tariff[tariff_id];
if((commTariff->cfChargeAmount*commTariff->cugChargeUnit)>
(commTariff->cugChargeAmount*commTariff->cfChargeUnit))
return 1;
else
return 0;
}
int BillingProc(_state_data *shmp, int sub_flag0)
{
int duration=0,overdraft=0,sub_flag;
int cos_id;
COSTable *cosTableItem;
CosServiceControl *serviceControlItem = NULL, *mtServiceCtrItem = NULL;
PutLogFunID("BillingProc");
sub_flag = sub_flag0;
cos_id = shmp->caller_info.cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
serviceControlItem = &cosTableItem->serviceControl[0];
if (sub_flag || shmp->process_info.favoriteCall == FRIEND_FAMILY_FREE_CALL)
{
if(shmp->context_info.callType == CT_MT_CALL)
{
shmp->process_info.tariff_flag =
GetMTTariffData(shmp,
shmp->called_info.location,
&shmp->process_info.tariff,
&shmp->called_info,
&shmp->charge_info);
}
else
{
if(shmp->process_info.serviceType == SRV_CRD
||
(shmp->process_info.serviceType == SRV_NORMAL_MO_CALL
&&
shmp->process_info.callConnected == 1
&&
!ppsParam.serviceControl.vms_allways_go))
{
GetMOTariffData(shmp, &shmp->process_info.tariff, (char *)shmp->charge_info.number, shmp->caller_info.location);
shmp->process_info.tariff_flag = 1;
shmp->caller_info.valid_time = 12*ONE_MINUTE_STATE_TIME;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = 12*ONE_MINUTE_STATE_TIME;
shmp->called_info.fee = 0;
return 1;
}
if(shmp->context_info.callType == CT_MO_CALL &&
cosTableItem->smsNotificationInquiry[0].smsNotificationWhenBalanceInsufficient)
if(GetBalanceWithPromotionControl(shmp,&shmp->caller_info)<
cosTableItem->smsNotificationInquiry[0].insufficientBalanceThreshold)
{
shmp->process_info.pre_warning = 1;
shmp->process_info.voiceID = PRE_WARNING_LOW_BALANCE;
}
if(shmp->process_info.mnp_status)
{
char billing_prefix[64];
sprintf(billing_prefix,"%s%s",shmp->process_info.routing_number,
shmp->called_info.number);
shmp->process_info.tariff_flag =
GetMOTariffData(shmp,&shmp->process_info.tariff, billing_prefix, shmp->caller_info.location);
/* parameter: continue or release the call */
if(shmp->process_info.tariff_flag==0)
{
if((logMsgFlag & 0x01) || shmp->process_info.logMsisdn)
{
DebugMsg(debugmib.display.asciiOut,
"\33[33m Calling ported number, but no RN+MSISDN(%s) billing prefix\33[0m",
billing_prefix);
DebugMsg(debugmib.display.asciiOut,
"\33[33m Use dialing prefix %s as billing prefix\33[0m",
shmp->charge_info.number);
}
shmp->process_info.tariff_flag =
GetMOTariffData(shmp, &shmp->process_info.tariff,
(char *)shmp->charge_info.number,
shmp->caller_info.location);
}
else
{
strcpy((char *)shmp->charge_info.number, billing_prefix);
}
}
else
{
shmp->process_info.tariff_flag =
GetMOTariffData(shmp,&shmp->process_info.tariff,
(char *)shmp->charge_info.number,
shmp->caller_info.location);
}
/* check MO tariff cap flag here */
/* added for cap call, 2007-10-25 */
shmp->process_info.cap_flag = shmp->process_info.tariff.cap_flag;
// Check Cap or Bundle is used================================
if(serviceControlItem->cap_or_bundle_in_tariff)// bundle is used, so we can set bundle flag and clear cap flag
{
shmp->process_info.bundle_flag = shmp->process_info.cap_flag; /* cap flag is reused as bundle call */
shmp->process_info.cap_flag = 0;
}
//==================================================
if(shmp->process_info.cap_flag>0)
{
// DebugMsg(debugmib.display.asciiOut,"CAP call, flag: %d",
// shmp->process_info.cap_flag);
shmp->caller_info.location = GetSubsCapTariffID(shmp,CAP_CALL);
GetMOTariffData(shmp,&shmp->process_info.tariff,
(char *)shmp->charge_info.number,
shmp->caller_info.location);
}
if(shmp->process_info.favoriteCall)
{
if(CheckFriendFamilyPlanFreeCallOrSMS(shmp->caller_info.head, shmp->caller_info.tail, 0, shmp->process_info.duration/CYCLE_STATE_INTERVAL))
{
shmp->process_info.favoriteCall = FRIEND_FAMILY_FREE_CALL;
memset(&shmp->process_info.tariff.tierRating, 0x00, sizeof(TIER_RATING));
shmp->process_info.tariff.adjustment = 0;
shmp->process_info.tariff.cap_flag = 0;
}
else
{
IncreaseFriendFamilyFreeCallDuration(shmp->caller_info.head,
shmp->caller_info.tail,
shmp->process_info.duration);
shmp->process_info.favoriteCall = FRIEND_FAMILY_CALL;
}
}
if(serviceControlItem->moThresholdSet && shmp->process_info.favoriteCall != FRIEND_FAMILY_FREE_CALL)
{
if((GetBalanceWithPromotionControl(shmp,&shmp->caller_info)+GetOverdraft(&shmp->caller_info))
< (serviceControlItem->moMinimumBalance))
{
shmp->caller_info.valid_time = 0;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = 0;
shmp->called_info.fee = 0;
return 0;
}
}
}
}// if sub_flag
switch(shmp->context_info.callType){
case CT_MT_CALL:
switch(shmp->called_info.status)
{
case T_FRESH:
case T_SUSPEND:
case T_BLACKLIST:
case T_EXTERNAL:
case T_RELEASED:
shmp->caller_info.valid_time = 0;
shmp->called_info.valid_time = 0;
shmp->process_info.tcos = CALLED_STATUS_ERROR;
shmp->process_info.voiceID = MT_ERROR_ACCOUNT_STATUS;
return FALSE;
break;
default:
break;
}
// Check Cap or Bundle is used================================
mtServiceCtrItem = &ppsParam.ppsTables.cosTable[shmp->called_info.cos_id].serviceControl[0];
if(mtServiceCtrItem->cap_or_bundle_in_tariff)// bundle is used, so we can set bundle flag
{
shmp->process_info.bundle_flag = shmp->process_info.tariff.cap_flag;
}
//==================================================
if(shmp->process_info.bundle_flag)
{
int left_mt_voice_seconds = 0;
left_mt_voice_seconds = pps_get_account_bundle_mt_voice(shmp);
if(left_mt_voice_seconds > 0)
{
if(left_mt_voice_seconds > shmp->process_info.tariff.unit_time)
left_mt_voice_seconds = shmp->process_info.tariff.unit_time;
shmp->caller_info.valid_time = left_mt_voice_seconds*CYCLE_STATE_INTERVAL;
shmp->caller_info.fee = 0;
shmp->called_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
//DebugMsg(debugmib.display.asciiOut, "BillingProc()->%s allocate bundle mt voice[%d]",
// shmp->caller_info.number, left_mt_voice_seconds);
return 1;
}
else
{
/*
if(shmp->process_info.duration > 1)
{
subscribe_bundle_plan_send_used_up_info(shmp->caller_info.number, SMS_BUNDLE_PLAN_VOICE_USEDUP);
}
*/
shmp->process_info.bundle_flag = 0;
}
}
if(shmp->process_info.chargedTime==0 && shmp->process_info.tariff.free_time)
{
shmp->called_info.valid_time =
shmp->process_info.tariff.free_time*CYCLE_STATE_INTERVAL;
shmp->called_info.fee = 0;
}
else
{
sub_flag = shmp->process_info.chargedTime;
if(shmp->process_info.tariff.free_time)
sub_flag = shmp->process_info.chargedTime - 1;
overdraft = GetOverdraft(&shmp->called_info);
if(!sub_flag && overdraft<0){
overdraft = 0;
}
shmp->called_info.valid_time =
GetValidTime( shmp,
tvnow.tv_sec,
//shmp->cdr_info.answertime,
&shmp->process_info.tariff,
GetBalanceWithPromotionControl(shmp,&shmp->called_info),
sub_flag,
overdraft);
duration = (int)( shmp->called_info.valid_time / CYCLE_STATE_INTERVAL);
shmp->called_info.fee = TimeToCharge(shmp,&shmp->process_info.tariff, duration, tvnow.tv_sec,sub_flag);
if(isPoolChildReachFeeLimit(&shmp->called_info) == 2)
{
pps_print_error(shmp->process_info.logMsisdn,"%s child account,reach limited fee",shmp->called_info.number);
shmp->caller_info.valid_time = 0;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = 0;
shmp->called_info.fee = 0;
shmp->process_info.tcos = CALLER_REACH_CHARGE_LIMIT;
shmp->process_info.pre_warning = 1;
shmp->process_info.voiceID = PRE_WARNING_LOW_BALANCE;
return -1;
}
}
shmp->caller_info.fee = 0;
shmp->caller_info.valid_time = shmp->called_info.valid_time;
break;
case CT_MF_CALL:
case CT_MO_CALL:
if(shmp->process_info.serviceType == SRV_CRD
||
(shmp->process_info.serviceType == SRV_NORMAL_MO_CALL
&&
shmp->process_info.callConnected == 1
&&
!ppsParam.serviceControl.vms_allways_go))
{
shmp->process_info.tariff_flag = 1;
shmp->caller_info.valid_time = 6*ONE_MINUTE_STATE_TIME;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = 6*ONE_MINUTE_STATE_TIME;
shmp->called_info.fee = 0;
return 1;
}
switch(shmp->caller_info.status)
{
case T_FRESH:
case T_SUSPEND:
case T_BLACKLIST:
case T_EXTERNAL:
case T_RELEASED:
shmp->caller_info.valid_time = 0;
shmp->called_info.valid_time = 0;
shmp->process_info.tcos = CALLER_STATUS_ERROR;
shmp->process_info.voiceID = ERROR_ACCOUNT_STATUS;
return FALSE;
break;
default:
break;
}
overdraft = GetOverdraft(&shmp->caller_info);
if(shmp->process_info.bundle_flag )/* bundle mo call charging */
{
int left_mo_voice_seconds = 0;
left_mo_voice_seconds = pps_get_account_bundle_mo_voice(shmp);
if(left_mo_voice_seconds > 0)
{
if(left_mo_voice_seconds > shmp->process_info.tariff.unit_time)
left_mo_voice_seconds = shmp->process_info.tariff.unit_time;
shmp->caller_info.valid_time = left_mo_voice_seconds*CYCLE_STATE_INTERVAL;
shmp->caller_info.fee = 0;
shmp->called_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
//DebugMsg(debugmib.display.asciiOut, "BillingProc()->%s allocate bundle mo voice[%d]",
// shmp->caller_info.number, left_mo_voice_seconds);
return 1;
}
else
{
/*
if(shmp->process_info.duration > 1)
{
subscribe_bundle_plan_send_used_up_info(shmp->caller_info.number, SMS_BUNDLE_PLAN_VOICE_USEDUP);
}
*/
shmp->process_info.bundle_flag = 0;
}
}
if(shmp->process_info.chargedTime==0 && shmp->process_info.tariff.free_time)
{
shmp->caller_info.valid_time =
shmp->process_info.tariff.free_time*CYCLE_STATE_INTERVAL;
shmp->caller_info.fee = 0;
if(GetBalanceWithPromotionControl(shmp,&shmp->caller_info)+overdraft< getCurrentFee(shmp))
{
shmp->caller_info.valid_time = 0;
}
}
else
{
if(shmp->process_info.cap_flag>0 && sub_flag0 == 0) /* re-get tariff for cap call during the call */
{
shmp->caller_info.location = GetSubsCapTariffID(shmp,CAP_CALL);
GetMOTariffData(shmp,&shmp->process_info.tariff,
(char *)shmp->charge_info.number,
shmp->caller_info.location);
}
sub_flag = shmp->process_info.chargedTime;
if(shmp->process_info.tariff.free_time)
sub_flag = shmp->process_info.chargedTime - 1;
if(!sub_flag && overdraft<0){
overdraft = 0;
}
shmp->caller_info.valid_time =
GetValidTime( shmp,
tvnow.tv_sec,
//shmp->cdr_info.answertime,
&shmp->process_info.tariff,
GetBalanceWithPromotionControl(shmp,&shmp->caller_info),
sub_flag,
overdraft);
duration = (int)( shmp->caller_info.valid_time
/ CYCLE_STATE_INTERVAL);
shmp->caller_info.fee = TimeToCharge(shmp,&shmp->process_info.tariff, duration,tvnow.tv_sec,sub_flag);
if(isPoolChildReachFeeLimit(&shmp->caller_info) == 2)
{
pps_print_error(shmp->process_info.logMsisdn,"%s child account,reach limited fee",shmp->caller_info.number);
shmp->caller_info.valid_time = 0;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = 0;
shmp->called_info.fee = 0;
shmp->process_info.tcos = CALLER_REACH_CHARGE_LIMIT;
shmp->process_info.pre_warning = 1;
shmp->process_info.voiceID = PRE_WARNING_LOW_BALANCE;
return -1;
}
}
shmp->called_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
break;
default:
shmp->caller_info.valid_time = 0;
shmp->called_info.valid_time = 0;
break;
}
shmp->process_info.chargedTime ++;
return SUCCESS;
}
int crm_check_if_cug_call(_account_info *caller, _account_info *called)
{
if(caller == NULL || called == NULL)
return 0;
if(caller->cug_id == 0 || called->cug_id == 0)
return 0;
if(caller->cug_id != called->cug_id)
return 0;
return 1;
}
extern int ocs_get_crm_free_seconds();
int BillingProc_crm(_state_data *shmp, int sub_flag0)
{
int duration=0,overdraft=0,sub_flag;
int cos_id;
COSTable *cosTableItem;
//CosServiceControl *mtServiceCtrItem = NULL;//*serviceControlItem = NULL,
char prefix[128], areaName[32]="";
PutLogFunID("BillingProc_crm");
sub_flag = sub_flag0;
cos_id = shmp->caller_info.cos_id;
cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
//serviceControlItem = &cosTableItem->serviceControl[0];
if(shmp->context_info.callType == CT_MT_CALL)
{
switch(shmp->called_info.status)
{
case T_FRESH:
//case T_SUSPEND:
case T_BLACKLIST:
case T_EXTERNAL:
case T_DISABLE:
case T_RELEASED:
shmp->caller_info.valid_time = 0;
shmp->called_info.valid_time = 0;
shmp->process_info.tcos = CALLER_STATUS_ERROR;
shmp->process_info.voiceID = ERROR_ACCOUNT_STATUS;
return FALSE;
break;
default:
break;
}
shmp->process_info.tariff_flag = 1;
shmp->caller_info.valid_time = 12*ONE_MINUTE_STATE_TIME;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = 12*ONE_MINUTE_STATE_TIME;
shmp->called_info.fee = 0;
shmp->process_info.call_type = CT_LOCAL_CALL_IN;
if(ocs_get_charge_prefix( (char *)shmp->caller_info.number, prefix, areaName, &shmp->process_info.tariff.call_type) == 0)
return 1;
if(shmp->process_info.tariff.call_type == CT_LOCAL_CALL_OUT) //to get incoming call type
{
shmp->process_info.tariff.call_type = CT_LOCAL_CALL_IN;
shmp->process_info.call_type = CT_LOCAL_CALL_IN;
}
else if(shmp->process_info.tariff.call_type == CT_TRUNK_CALL_OUT)
{
shmp->process_info.tariff.call_type = CT_TRUNK_CALL_IN;
shmp->process_info.call_type = CT_TRUNK_CALL_IN;
}
else if(shmp->process_info.tariff.call_type == CT_IDD_CALL_OUT)
{
shmp->process_info.tariff.call_type = CT_IDD_CALL_IN;
shmp->process_info.call_type = CT_IDD_CALL_IN;
}
return 1;
}
if(shmp->process_info.rest_if.query_tariff_status == 2)
{
shmp->process_info.tariff_flag = 1;
shmp->process_info.tariff.unit_time = shmp->process_info.rest_if.unit;
shmp->process_info.tariff.tierRating.tierNumber = 0;
shmp->process_info.tariff.tierRating.rating[0].base_fee = shmp->process_info.rest_if.unit_charge;
shmp->process_info.tariff.tierRating.rating[0].units = 1;
shmp->process_info.tariff.tierRating.rating[0].long_distance_fee = 0;
shmp->process_info.tariff.mini_unit = 1;
}
else
{
shmp->process_info.tariff_flag = 0;
}
switch(shmp->caller_info.status)
{
case T_FRESH:
case T_SUSPEND:
case T_BLACKLIST:
case T_EXTERNAL:
case T_DISABLE:
case T_RELEASED:
shmp->process_info.tariff_flag = 1;
shmp->caller_info.valid_time = 0;
shmp->called_info.valid_time = 0;
shmp->process_info.tcos = CALLER_STATUS_ERROR;
shmp->process_info.voiceID = ERROR_ACCOUNT_STATUS;
shmp->process_info.pre_warning = 1;
return FALSE;
break;
default:
break;
}
if(crm_check_if_cug_call(&shmp->caller_info, &shmp->called_info))
//if(shmp->caller_info.cug_id>0 && (shmp->caller_info.cug_id == shmp->called_info.cug_id ))
{
shmp->process_info.tariff_flag = 1;
shmp->caller_info.valid_time = 120*ONE_MINUTE_STATE_TIME;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = 120*ONE_MINUTE_STATE_TIME;
shmp->called_info.fee = 0;
return 1;
}
shmp->caller_info.free_flag = 0;
if(shmp->context_info.callType == CT_MO_CALL &&
cosTableItem->smsNotificationInquiry[0].smsNotificationWhenBalanceInsufficient)
{
if(GetBalanceWithPromotionControl(shmp,&shmp->caller_info)<
cosTableItem->smsNotificationInquiry[0].insufficientBalanceThreshold)
{
shmp->process_info.pre_warning = 1;
shmp->process_info.voiceID = PRE_WARNING_LOW_BALANCE;
}
}
else
{
if ((shmp->process_info.rest_if.total_plan_value> 0) &&
(shmp->process_info.rest_if.used_plan_value < shmp->process_info.rest_if.total_plan_value))
{
if(sub_flag)
{
if(shmp->process_info.tariff.call_type != CT_IDD_CALL_OUT)
{
int free_secs = ocs_get_crm_free_seconds();
if(free_secs>0)
{
shmp->caller_info.free_flag = 1;
shmp->caller_info.valid_time = free_secs*CYCLE_STATE_INTERVAL;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
shmp->called_info.fee = 0;
return 1;
}
}
}
int left_plan_value = 0;
left_plan_value = (shmp->process_info.rest_if.total_plan_value - shmp->process_info.rest_if.used_plan_value);
if(left_plan_value > shmp->process_info.tariff.unit_time)
left_plan_value = shmp->process_info.tariff.unit_time;
shmp->caller_info.valid_time = (left_plan_value) * CYCLE_STATE_INTERVAL;
shmp->caller_info.fee = 0;
goto billing_crm_ret;
}
{
shmp->caller_info.valid_time =
GetValidTime( shmp,
tvnow.tv_sec,
&shmp->process_info.tariff,
GetBalanceWithPromotionControl(shmp,&shmp->caller_info),
sub_flag,
overdraft);
duration = (int)( shmp->caller_info.valid_time/CYCLE_STATE_INTERVAL);
shmp->caller_info.fee = TimeToCharge(shmp,&shmp->process_info.tariff, duration,tvnow.tv_sec,sub_flag);
}
if(sub_flag && (shmp->caller_info.valid_time) > CYCLE_STATE_INTERVAL)
{
if(shmp->process_info.tariff.call_type != CT_IDD_CALL_OUT)
{
int free_secs = ocs_get_crm_free_seconds();
if(free_secs>0)
{
shmp->caller_info.free_flag = 1;
shmp->caller_info.valid_time = free_secs*CYCLE_STATE_INTERVAL;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
shmp->called_info.fee = 0;
return 1;
}
}
}
}
billing_crm_ret:
shmp->called_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
shmp->process_info.chargedTime ++;
return SUCCESS;
}
extern float ocs_get_calling_card_left_balance(int head, int tail);
int BillingProc_ccc(_state_data *shmp, int sub_flag0)
{
int duration=0,overdraft=0,sub_flag;
//int cos_id;
//COSTable *cosTableItem;
//CosServiceControl *serviceControlItem = NULL, *mtServiceCtrItem = NULL;
int balance = 0;
PutLogFunID("BillingProc_ccc");
sub_flag = sub_flag0;
//cos_id = shmp->caller_info.cos_id;
//cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
//serviceControlItem = &cosTableItem->serviceControl[0];
shmp->caller_info.location = shmp->caller_info.cos_id;
if (sub_flag )
{
shmp->process_info.tariff_flag =
GetMOTariffData(shmp,&shmp->process_info.tariff,
(char *)shmp->charge_info.number,
shmp->caller_info.location);
balance = (int)ocs_get_calling_card_left_balance(shmp->card_info.cardhead, shmp->card_info.cardtail);
shmp->card_info.balance = balance;
}// if sub_flag
else
{
if(shmp->card_info.balance > shmp->card_info.cc_call_charge)
balance = shmp->card_info.balance;
else
balance = 0;
}
switch(shmp->context_info.callType){
case CT_MO_CC_CALL:
if( shmp->process_info.callConnected == 1 )
{
shmp->process_info.tariff_flag = 1;
shmp->caller_info.valid_time = 6*ONE_MINUTE_STATE_TIME;
shmp->caller_info.fee = 0;
shmp->called_info.valid_time = 6*ONE_MINUTE_STATE_TIME;
shmp->called_info.fee = 0;
return 1;
}
if(shmp->process_info.chargedTime==0 && shmp->process_info.tariff.free_time)
{
shmp->caller_info.valid_time =
shmp->process_info.tariff.free_time*CYCLE_STATE_INTERVAL;
shmp->caller_info.fee = 0;
}
else
{
if(shmp->process_info.cap_flag>0 && sub_flag0 == 0) /* re-get tariff for cap call during the call */
{
GetMOTariffData(shmp,&shmp->process_info.tariff,
(char *)shmp->charge_info.number,
shmp->caller_info.location);
}
sub_flag = shmp->process_info.chargedTime;
if(shmp->process_info.tariff.free_time)
sub_flag = shmp->process_info.chargedTime - 1;
shmp->caller_info.valid_time =
GetValidTime( shmp,
tvnow.tv_sec,
&shmp->process_info.tariff,
balance,
sub_flag,
overdraft);
duration = (int)( shmp->caller_info.valid_time / CYCLE_STATE_INTERVAL);
shmp->caller_info.fee = TimeToCharge(shmp,&shmp->process_info.tariff, duration,tvnow.tv_sec,sub_flag);
}
shmp->called_info.fee = 0;
shmp->called_info.valid_time = shmp->caller_info.valid_time;
break;
default:
shmp->caller_info.valid_time = 0;
shmp->called_info.valid_time = 0;
break;
}
shmp->process_info.chargedTime ++;
return SUCCESS;
}
int IsEnableToCall_ccc(int proc_id)
{
_state_data *shmp=(_state_data *) &smshm_ptr->state_data;
//int call_type=0,rst;
//COSTable *cosTableItem;
PutLogFunID("IsEnableToCall");
shmp += proc_id;
//call_type = shmp->context_info.callType;
if(shmp->process_info.tcos == SRVICE_NOT_SUBSCRIBERED)
return FALSE;
if(shmp->process_info.tariff_flag ==0)
{
shmp->process_info.tcos = TARIFF_NOT_SET;
shmp->process_info.voiceID = CALLED_TARIFF_NOT_SET;
return FALSE;
}
if(shmp->caller_info.valid_time <= 0)
{
shmp->process_info.tcos = CALLER_CREDIT_OUT;
shmp->process_info.voiceID = LOW_ACCOUNT_BALANCE;
return FALSE;
}
return TRUE;
}
void
SetCallType(_state_data *shmp, int type)
{
switch(type)
{
case 0:
if(shmp->context_info.callType == CT_MT_CALL)
shmp->process_info.call_type = CT_LOCAL_CALL_IN;
else
shmp->process_info.call_type = CT_LOCAL_CALL_OUT;
break;
case 1:
shmp->process_info.call_type = CT_NDD_CALL_OUT;
break;
case 2:
shmp->process_info.call_type = CT_IDD_CALL_OUT;
break;
case 4:
shmp->process_info.call_type = CT_LOCAL_CALL_IN;
break;
case 5:
shmp->process_info.call_type = CT_TRUNK_CALL_IN;
break;
default:
shmp->process_info.call_type = type;
break;
}
}
const int
IsNormalRechargeCard(_state_data *shmp)
{
u_char bcd[CONTEXT_BLOCK_SIZE];
u_long expiration=0;
PutLogFunID("IsNormalRechargeCard");
memcpy(bcd, &shmp->context_info.context[1], sizeof(_RCI_));
expiration = ((_RCI_ *)bcd)->expiry_date;
if (((_RCI_ *) bcd)->card_status == T_FRESH
&& (u_long) tvnow.tv_sec < expiration)
{
return TRUE;
}
else
{
return FALSE;
}
}
int GetRechargeCardFaceValue(_state_data *shmp)
{
u_char bcd[CONTEXT_BLOCK_SIZE];
PutLogFunID("GetRechargeCardFaceValue");
memcpy(bcd, shmp->context_info.context,//+1 , //sizeof(_RSIR_),
sizeof(_RCI_));
return ((_RCI_ *) bcd)->face_value;
}
int GetRechargeCardValidTime(_state_data *shmp)
{
u_char bcd[CONTEXT_BLOCK_SIZE];
PutLogFunID("GetRechargeCardValidTime");
memcpy(bcd, shmp->context_info.context,//+1, //+sizeof(_RSIR_),
sizeof(_RCI_));
return ((_RCI_ *) bcd)->valid_time;
}
static void PureDigitAscii(u_char *string)
{
int loop,len;
len = strlen((char *)string);
for(loop=0;loop<len;loop++)
{
if(string[loop]<'0' || string[loop]>'9')
{
string[loop] = 0;
break;
}
}
string[loop] = 0;
}
char
GetTariffLacInfo(u_char *cgi)
{
int loc = -1, loop, matchFlag=0,len;
u_short cell, lac;
u_char MCC[32]={0},MNC[32]={0};
BasicTariffZone *pBTZ;
PutLogFunID("GetTariffLacInfo");
ppsBcdToAsciiR((char *)MCC,cgi,4);
PureDigitAscii(MCC);
ppsBcdToAsciiR((char *)MNC,&cgi[2],2);
PureDigitAscii(MNC);
lac = cgi[3] * 256 + cgi[4];
cell = cgi[5] * 256 + cgi[6];
if(cgi[0]==0 && lac==0 && cell==0) //CF /MT call
return loc;
for(loop=0;loop<MaxBasicTariffZoneItem;loop++)
{
pBTZ = &ppsParam.ppsTables.basicTariffZone[loop];
if(pBTZ->existFlag == FALSE)
continue;
matchFlag = 0;
len = strlen((char *)pBTZ->mcc);
if(len == 0)
continue;
if(memcmp(pBTZ->mcc,MCC,len) == 0)
{
len = strlen((char *)pBTZ->mnc);
if(len == 0)
{
matchFlag = 1;
}
else if(memcmp(pBTZ->mnc,MNC,len) ==0 )
{
if(ppsParam.serviceControl.charge_by_lac_flag == 1)
{
if(pBTZ->cellId == cell)
matchFlag = 1;
}
else
{
if(pBTZ->lac != 0xFFFF)
{
if(pBTZ->cellId != 0xFFFF)
{
if(pBTZ->cellId == cell
&& pBTZ->lac == lac)
{
matchFlag = 1;
}
}
else if(pBTZ->lac == lac)
{
matchFlag = 1;
}
}
else
{
matchFlag = 1;
}/* lac */
}
}/* mcc&mnc */
if(matchFlag)
{
return loop;
}
}//if mcc
}/* for */
return loc;
}
int GetAccountZoneIDByLocationInfo(int index)
{
return ppsParam.ppsTables.basicTariffZone[index].moTariffId%MAX_ZONE_NUM;
}
int GetAccountMTZoneIDByLocationInfo(int index)
{
return ppsParam.ppsTables.basicTariffZone[index].mtTariffId%MAX_ZONE_NUM;
}
void CheckWetherRoamingUser(_state_data *shmp)
{
_prepaid_data *user_shmp=&ramshm_ptr->prepaid_data;
_account_info *ptr;
int loop;
PutLogFunID("CheckWetherRoamingUser");
ptr = &shmp->caller_info;
shmp->process_info.roamingFlag = 1;
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
for(loop=0;loop<MAX_HOME_LOCATION;loop++)
{
if(ptr->location ==
user_shmp->prepaid_info[ptr->head][ptr->tail].home_location[loop])
{
shmp->process_info.roamingFlag = 0;
return;
}
}
}
pps_print_event(shmp->process_info.logMsisdn,"%s is a MO roaming user",shmp->caller_info.number);
}
void CheckWetherRoamingMTUser(_state_data *shmp)
{
_prepaid_data *user_shmp=&ramshm_ptr->prepaid_data;
_account_info *ptr;
int loop;
PutLogFunID("CheckWetherRoamingMTUser");
ptr = &shmp->called_info;
shmp->process_info.roamingFlag = 1;
if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
{
for(loop=0;loop<MAX_HOME_LOCATION;loop++)
{
if(ptr->location ==
user_shmp->prepaid_info[ptr->head][ptr->tail].home_location[loop])
{
shmp->process_info.roamingFlag = 0;
return;
}
}
}
pps_print_event(shmp->process_info.logMsisdn,"%is a MT roaming user",shmp->called_info.number);
}
/* get HPLMN from xapp , 2003-10-23 */
void SetRoamingFlag(_state_data *shmp)
{
char plmn[32]={""},buf[32]={""};
int plmnlen;
u_char CC[32],NDC[32];
PutLogFunID("SetRoamingFlag");
xap_get_cc(CC);
xap_get_ndc(NDC);
BcdToAscii(plmn,CC,4);
StringCut(plmn,'E');
BcdToAscii(buf,NDC,6);
StringCut(buf,'E');
strcat(plmn,buf);
plmnlen = strlen(plmn);
if(!strncasecmp(shmp->cdr_info.locationNumber,plmn,plmnlen))
{
shmp->process_info.roamingFlag = 0;
}else{
shmp->process_info.roamingFlag = 1;
}
}
void
SetLocationInfo(u_char *cgi, u_short proc_id)
{
_state_data *shmp=(_state_data *) &smshm_ptr->state_data;
PutLogFunID("SetLocationInfo");
shmp += proc_id;
memcpy(shmp->cdr_info.cgi,cgi,7);
}
u_long
GetTimeFunnel(u_short hour, u_short minute, u_short second)
{
int funnel=0;
PutLogFunID("GetTimeFunnel");
funnel = ((hour-GetTmHour()) * 60 * 60 )
+ ((minute - GetTmMinute() ) * 60)
+ (second - GetTmSecond());
return (funnel <= 0) ? (funnel+24*60*60)*CYCLE_STATE_INTERVAL
: funnel*CYCLE_STATE_INTERVAL;
}
int
IsEnablePeriodicCharge(int head, int tail)
{
_prepaid_info *shmp=NULL;
PutLogFunID("IsEnablePeriodicCharge");
shmp = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
if ( shmp->msisdn[MAX_MSISDN_BLEN-1] != 0
&& ((shmp->status == T_NORMAL )
|| (shmp->status == T_BLACKLIST)
|| (shmp->status == T_SUSPEND ))
&& shmp->mt_expiration_date>=tvnow.tv_sec
&& shmp->rent_type != 0)
return TRUE;
else
return FALSE;
}
int
IsEnablePeriodicAction(int head, int tail)
{
_prepaid_info *shmp=NULL;
PutLogFunID("IsEnablePeriodicAction");
shmp = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
if ( shmp->msisdn[MAX_MSISDN_BLEN-1] != 0
&& ((shmp->status == T_NORMAL )
|| (shmp->status == T_BLACKLIST)
|| (shmp->status == T_SUSPEND ))
&& shmp->mt_expiration_date>=tvnow.tv_sec)
return TRUE;
else
return FALSE;
}
float GetAccountBalance(int head, int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetAccountBalance");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
return (shmp->prepaid_info[head][tail].balance +
shmp->prepaid_info[head][tail].promo_balance);
return FALSE;
}
int GetAccountVoiceID(int head,int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetAccountVoiceID");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
return shmp->prepaid_info[head][tail].language_type;
return 0;
}
int
GetUserType(int head, int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetUserType");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
return shmp->prepaid_info[head][tail].rent_type;
return FAILURE;
}
int
GetPeriodicChargeDate(int tariff_id,int id)
{
_rent_tariff *shmp=NULL;
PutLogFunID("GetPeriodicChargeDate");
if (id < MAX_RENT_TARIFF) {
shmp = &ramshm_ptr->tariff_data.rent_tariff[tariff_id][id];
return shmp->charge_date;
} else
return 32;
}
int
GetPeriodicTariffFee(int tariff_id,int id)
{
_rent_tariff *shmp=NULL;
int rent_amount = 0;
PutLogFunID("GetPeriodicTariffFee");
if (id < MAX_RENT_TARIFF) {
shmp = &ramshm_ptr->tariff_data.rent_tariff[tariff_id][id];
rent_amount = (int)shmp->rent_amount;
}
return rent_amount;
}
short
GetPeriodicTariffDate(int tariff_id,int id)
{
_rent_tariff *shmp=NULL;
PutLogFunID("GetPeriodicTariffDate");
if (id < MAX_RENT_TARIFF) {
shmp = &ramshm_ptr->tariff_data.rent_tariff[tariff_id][id];
return shmp->charge_date;
} else
return FAILURE;
}
short
GetPeriodicTariffType(int tariff_id,int id)
{
_rent_tariff *shmp=NULL;
PutLogFunID("GetPeriodicTariffType");
if (id < MAX_RENT_TARIFF) {
shmp = &ramshm_ptr->tariff_data.rent_tariff[tariff_id][id];
return shmp->rent_type;
} else
return FAILURE;
}
void
UpdateAccountBalance(int head, int tail, float charge)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateAccountBalance");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
shmp->prepaid_info[head][tail].balance = shmp->prepaid_info[head][tail].balance + charge;
if(shmp->prepaid_info[head][tail].balance<0)
{
shmp->prepaid_info[head][tail].balance = 0;
}
}
}
void UpdateAccountOverdraft(int head, int tail, long overdraft)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateAccountOverdraft");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
shmp->prepaid_info[head][tail].overdraft = overdraft;
}
void UpdateAccountPromotionBalance(int head, int tail, float charge)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateAccountPromotionBalance");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
shmp->prepaid_info[head][tail].promo_balance = shmp->prepaid_info[head][tail].promo_balance+charge;
}
void UpdateAccountPromotionExpiryDay(int head, int tail, int days)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateAccountPromotionExpiryDay");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
if(days>0 )
{
if(shmp->prepaid_info[head][tail].promo_date< tvnow.tv_sec + days*24*3600)
shmp->prepaid_info[head][tail].promo_date = tvnow.tv_sec + days*24*3600;
}
else
shmp->prepaid_info[head][tail].promo_date =
shmp->prepaid_info[head][tail].mo_expiration_date;
}
}
void UpdateAccountCUGStatus(_prepaid_info *user_info_ptr, u8 cug_status)
{
if(user_info_ptr == NULL)
return;
user_info_ptr->crm_info.vas_cug_state = cug_status;
}
u_long
GetAccountFirstUsedDate(int head, int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetAccountFirstUsedDate");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
return shmp->prepaid_info[head][tail].first_used_date;
return FALSE;
}
int MsisdnToLong(u_long *ulmsisdn, char *cmsisdn)
{
int len,len1;
char tmpbuf[64],buf[64];
PutLogFunID("MsisdnToLong");
len = cmsisdn[9];
if(len>18) len = 18;
len1 = len;
if(len %2 !=0) len1 = len + 1;
BcdToAscii(tmpbuf, (BYTE *)cmsisdn,len1);
memcpy(buf,tmpbuf,len);
buf[len] = 0;
*ulmsisdn = atol(buf);
return 1;
}
int
GetAccountMsisdnStr(int head, int tail,u_char *msisdn)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
int len;
PutLogFunID("GetAccountMsisdn");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
len = shmp->prepaid_info[head][tail].msisdn[MAX_MSISDN_BLEN-1];
BcdToAscii((char *)msisdn, shmp->prepaid_info[head][tail].msisdn, (len+1)/2*2);
msisdn[len]=0;
return TRUE;
}
return FALSE;
}
int
GetAccountMsisdn(int head, int tail,u_char *msisdn)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
int len;
PutLogFunID("GetAccountMsisdn");
if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT)
{
// MsisdnToLong(&msisdn,shmp->prepaid_info[head][tail].msisdn);
len = shmp->prepaid_info[head][tail].msisdn[MAX_MSISDN_BLEN-1];
memcpy(msisdn,shmp->prepaid_info[head][tail].msisdn,MAX_MSISDN_BLEN-1);
if(len%2==0){
msisdn[len/2]=0xFF;
}else{
msisdn[(len)/2] |= 0x0F;
}
return TRUE;
}
return FALSE;
}
void
UpdateAccountFirstUsedDate(int head, int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
char date_buf[32];
PutLogFunID("UpdateAccountFirstUsedDate");
GetTmDate(date_buf);
strcat(date_buf, "000000");
shmp->prepaid_info[head][tail].first_used_date =
MakeTime(NULL, date_buf);
}
void
UpdateAccountStatus(int head, int tail, int status)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateAccountStatus");
shmp->prepaid_info[head][tail].status = status;
}
void
UpdateAccountRechargeFail(int head, int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("UpdateAccountRechargeFail");
shmp->prepaid_info[head][tail].recharge_fail ++;
}
u_short
GetAccountRechargeFail(int head, int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("GetAccountRechargeFail");
return shmp->prepaid_info[head][tail].recharge_fail;
}
void
ResetAccountRechargeFail(int head, int tail)
{
_prepaid_data *shmp=&ramshm_ptr->prepaid_data;
PutLogFunID("ResetAccountRechargeFail");
shmp->prepaid_info[head][tail].recharge_fail = 0;
}
int isAccountExpired(_account_info *ptr)
{
if(GetExpiration(ptr) < tvnow.tv_sec)
return 1;
return 0;
}
/* If the call is valid or invalid
0: invalid, 1: valid
*/
int
IsEnableToCall(int proc_id)
{
_state_data *shmp=(_state_data *) &smshm_ptr->state_data;
int call_type=0,rst;
COSTable *cosTableItem;
PutLogFunID("IsEnableToCall");
shmp += proc_id;
call_type = shmp->context_info.callType;
if(shmp->process_info.tcos == SRVICE_NOT_SUBSCRIBERED)
return FALSE;
if(call_type == CT_MO_SM)
{
rst = isPoolChildReachSMSLimit(shmp);
if(rst)
{
switch(rst)
{
case 1:
shmp->process_info.tcos= CALLER_REACH_SMS_LIMIT;
break;
case 2:
shmp->process_info.tcos= CALLER_REACH_CHARGE_LIMIT;
break;
}
return FALSE;
}
if ((shmp->caller_info.valid_time > 0
&& tvnow.tv_sec <= GetExpiration(&shmp->caller_info)))
{
return TRUE;
}
if (tvnow.tv_sec > GetExpiration(&shmp->caller_info) )
{
shmp->process_info.tcos= CALLER_EXPIRIED;
return FALSE;
}
else if (shmp->caller_info.valid_time <= 0 )
{
shmp->process_info.tcos= CALLER_CREDIT_OUT;
return FALSE;
}
}
switch(call_type)
{
case CT_MT_CALL:
if(shmp->called_info.valid_time >0)
{
SetCallType(shmp,shmp->process_info.tariff.call_type);
if(tvnow.tv_sec>=GetIncomingExpiration(&shmp->called_info))
{
shmp->process_info.tcos= CALLED_EXPIRIED;
shmp->process_info.voiceID = MT_EXPIRIED_ACCOUNT;
return FALSE;
}
else
{
SetCallType(shmp,shmp->process_info.tariff.call_type);
}
}
else
{
if(shmp->called_info.status == T_NORMAL)
{
shmp->process_info.tcos = CALLED_CREDIT_OUT;
shmp->process_info.voiceID = MT_LOW_ACCOUNT_BALANCE;
}
else
{
shmp->process_info.tcos = CALLED_STATUS_ERROR;
shmp->process_info.voiceID = MT_ERROR_ACCOUNT_STATUS;
}
return FALSE;
}
if(shmp->process_info.tariff_flag ==0)
{
shmp->process_info.tcos = TARIFF_NOT_SET;
shmp->process_info.voiceID = CALLED_TARIFF_NOT_SET;
return FALSE;
}
break;
case CT_MO_CALL:
case CT_MF_CALL:
if(shmp->process_info.tariff_flag ==0)
{
shmp->process_info.tcos = TARIFF_NOT_SET;
shmp->process_info.voiceID = CALLED_TARIFF_NOT_SET;
return FALSE;
}
if(shmp->caller_info.valid_time >0)
{
cosTableItem = &ppsParam.ppsTables.cosTable[shmp->caller_info.cos_id];
if(tvnow.tv_sec>=GetExpiration(&shmp->caller_info))
{
if(call_type == CT_MO_CALL)
{
shmp->process_info.tcos = CALLER_EXPIRIED;
shmp->process_info.voiceID = EXPIRIED_ACCOUNT;
}
else
{
shmp->process_info.tcos= CALLED_EXPIRIED;
shmp->process_info.voiceID = MT_EXPIRIED_ACCOUNT;
}
return FALSE;
}
else if((call_type == CT_MO_CALL) &&
((tvnow.tv_sec+
(cosTableItem->smsNotificationInquiry[0].theDaysSendingSMSBeforeExpiredDay)*24*3600)
>=GetExpiration(&shmp->caller_info)))
{
shmp->process_info.pre_warning = 1;
shmp->process_info.voiceID = PRE_WARNING_EXPIRATION_DAY;
}
SetCallType(shmp,shmp->process_info.tariff.call_type);
}
else
{
if(shmp->caller_info.status == T_NORMAL)
{
if(call_type == CT_MO_CALL)
{
shmp->process_info.tcos = CALLER_CREDIT_OUT;
shmp->process_info.voiceID = LOW_ACCOUNT_BALANCE;
}
else
{
shmp->process_info.tcos = CALLED_CREDIT_OUT;
shmp->process_info.voiceID = MT_LOW_ACCOUNT_BALANCE;
}
}
return FALSE;
}
break;
default:
shmp->process_info.tcos = 255;
return FALSE;
break;
}
return TRUE;
}
void
SetCSTATimestamp(int instance, u_long timestamp)
{
PutLogFunID("SetCSTATimestamp");
pps_csta_buffer.csta_record[instance].timestamp = timestamp;
}
static int callTypeToCstaType(u_short callType)
{
switch(callType)
{
case CT_LOCAL_CALL_OUT:
case CT_TRUNK_CALL_OUT:
case CT_NDD_CALL_OUT:
case CT_IDD_CALL_OUT:
case CT_LOCAL_CALL_IN:
case CT_TRUNK_CALL_IN:
case CT_PERIODIC_CHARGE:
case CT_ASSISTED_UP:
case CT_ASSISTED_DOWN:
case CT_RECHARGE_SUCCESS:
case CT_RECHARGE_FAIL:
case CT_MO_SM:
case CT_DIRECT_DEBITING:
case CT_REFUND_ACCOUNT:
case CT_CONFERENCE_CALL:
case CT_THIRD_PARTY_CHARGE:
case CT_EMERGENCY_CALL:
return callType - PPS_CSTA_TYPE_BASE;
break;
case CT_BUNDLE_PLAN_CHARGE:
return CT_PERIODIC_CHARGE - PPS_CSTA_TYPE_BASE;
break;
case CT_GPRS:
case CT_GPRS_REFUND:
return SERVICE_GPRS;
break;
case CT_MO_CC_CALL:
return SERVICE_CCC;
default:
return -1;
break;
}
return -1;
}
int CDRStatistics(_tocdr_report* pbuf,float f_charge,ulong gprsVolume)
{
int charge=0, duration=0;
u_short type;
char buf[BUFSIZE];
int cstaType;
PutLogFunID("CDRStatistics");
type = pbuf->type[0] + pbuf->type[1] * 256;
memcpy(&charge , pbuf->charge, 4);
memcpy(&duration , pbuf->duration, 4 );
BcdToAscii(buf, pbuf->releasetime, 14);
if (type == CT_REFUND_ACCOUNT)
{
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.number ++;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.charge -= charge;
reportGprsCDRIncrement(0, -charge, 0);
}
else if (type == CT_DIRECT_DEBITING)
{
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.number ++;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.charge += charge;
reportGprsCDRIncrement(0, charge, 0);
}
cstaType = callTypeToCstaType(type);
if(cstaType<0)
return -1;
if(cstaType == SERVICE_GPRS)
{
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.gprsVolume += gprsVolume;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.number ++;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.charge += charge;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.duration += duration ;
}
else
{
pps_csta_buffer.csta_record[csta_old_instance].csta_type[cstaType].number ++;
pps_csta_buffer.csta_record[csta_old_instance].csta_type[cstaType].charge += charge;
pps_csta_buffer.csta_record[csta_old_instance].csta_type[cstaType].duration += duration ;
}
AddPPSStatistics(MIBPPS_CSTANUMBER,0);
#if DEBUG
if(logMsgFlag & 0x04)
DebugMsg(debugmib.display.asciiOut, "type:%d charge:%d duration:%d",
cstaType, charge, duration);
#endif
if(cstaType != SERVICE_GPRS)
reportCDRIncrement(type, duration, f_charge,gprsVolume);
else
reportGprsCDRIncrement(duration,f_charge,gprsVolume);
return 1;
}
int GprsCDRStatistics(_tocdr_report* pbuf,float f_charge,ulong gprsVolume)
{
u_long charge=0, duration=0;
u_short type,cstaType;
char buf[BUFSIZE];
PutLogFunID("GprsCDRStatistics");
type = pbuf->type[0] + pbuf->type[1] * 256;
memcpy(&charge , pbuf->charge, 4);
memcpy(&duration , pbuf->duration, 4 );
BcdToAscii(buf, pbuf->releasetime, 14);
cstaType = callTypeToCstaType(type);
if(cstaType<0)
return -1;
if( type == CT_GPRS_REFUND)
{
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.gprsVolume -= gprsVolume;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.number --;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.charge -= charge;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.duration -= duration ;
reportGprsCDRIncrement(duration, -f_charge, -gprsVolume);
}
else if(cstaType == SERVICE_GPRS)
{
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.gprsVolume += gprsVolume;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.number ++;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.charge += charge;
pps_csta_buffer.csta_record[csta_old_instance].gprsCsta.duration += duration ;
reportGprsCDRIncrement(duration,f_charge,gprsVolume);
AddPPSStatistics(MIBPPS_CSTANUMBER,0);
}
#if DEBUG
if(logMsgFlag & 0x04)
DebugMsg(debugmib.display.asciiOut, "type:%d charge:%d duration:%d volume:%ld",
cstaType, charge, duration,gprsVolume);
#endif
return 1;
}
int MsisdnToAscii(char *ascii_in, BYTE *cmsisdn)
{
int len,len1;
char tmpbuf[64];
PutLogFunID("MsisdnToAscii");
len = cmsisdn[MAX_MSISDN_BLEN-1];
len = len % 19;
len1 = len;
if(len%2 !=0) len1 = len + 1;
BcdToAscii(tmpbuf,cmsisdn,len1);
memcpy(ascii_in,tmpbuf,len);
ascii_in[len] = 0;
return 1;
}
int ppsInitCSTA()
{
time_t nowSec,nowSec1;
PutLogFunID("ppsInitCSTA");
nowSec = nowSec1 = tvnow.tv_sec;
nowSec = nowSec % (24 * 3600);
csta_now_instance = \
csta_old_instance = \
nowSec / (15 * 60);
SetCSTATimestamp(csta_old_instance, nowSec1);
return 1;
}
void
cstaInstanceCheck()
{
time_t nowSec,nowSec1;
PutLogFunID("cstaInstanceCheck");
nowSec = nowSec1 = tvnow.tv_sec;
nowSec = nowSec % (24 * 3600);
csta_now_instance = \
nowSec / (15 * 60);
if(csta_old_instance != csta_now_instance)
{
csta_old_instance = csta_now_instance;
memset(&pps_csta_buffer.csta_record[csta_now_instance],
0,
sizeof(_pps_csta_record));
SetCSTATimestamp(csta_old_instance, nowSec1);
}
}
int CheckWetherLocalNumber(char *number)
/*return value is the number property,
0=unknwon, 1=local, 2=national, 3=internationl
*/
{
char plmn[32]={""},buf[BUFSIZE]={""};
char ndc[32]={""},cc[32]={""};
int start,/*len,*/plmnlen,ndclen,cclen;
int retval=3;
u_char CC[32],NDC[32];
PutLogFunID("CheckWetherLocalNumber");
xap_get_cc(CC);
xap_get_ndc(NDC);
//len = strlen(number);
BcdToAscii(plmn,CC,4);
StringCut(plmn,'E');
cclen = strlen(plmn);
strcpy(cc,plmn);
BcdToAscii(buf,NDC,6);
StringCut(buf,'E');
strcpy(ndc,buf);
ndclen = strlen(buf);
strcat(plmn,buf);
plmnlen = strlen(plmn);
start = 0;
memcpy(buf,number,plmnlen);
buf[plmnlen] = 0;
if(!strncasecmp(buf,cc,cclen))
{
if(!strncasecmp(buf,plmn,plmnlen))
{
start += plmnlen;
retval = 1;
}
else
{
start += cclen;
retval = 2;
}
}
else if(ndclen>0 && !strncasecmp(buf,ndc,ndclen))
{
start += ndclen;
retval = 2;
}
// if((len-start)<0) start = len;
// memcpy(buf,&number[start],len-start);
// buf[len-start] = 0;
// strcpy(number,buf);
return retval;
}
int transferIddBillingPrefix(char *number) /* to check if idd/00idd billing prefix need to be tranferred by XAPP */
{
char inter_prefix[32];
char bufi[32];
int len;
PutLogFunID("transferIddBillingPrefix");
xap_get_interprefix((u8 *)inter_prefix);
BcdToAscii(bufi, (BYTE *)inter_prefix,4);
StringCut(bufi,'E');
len = strlen(bufi);
if(memcmp(number,bufi,len)) /* no international prefix */
{
return 1;
}
if(ppsParam.serviceControl.transfer_idd_prefix == 0) /* contains internaltion prefix, e.g 00, but not need to transfer it */
{
return 0;
}
return 1;
}
int AddNDC(char *number)
{
char bufndc[32],buf[BUFSIZE];
char NDC[32];
PutLogFunID("AddNDC");
xap_get_ndc((u8 *)NDC);
BcdToAscii(bufndc, (BYTE *)NDC,6);
StringCut(bufndc,'E');
strcpy(buf,bufndc);
strcat(buf,number);
strcpy(number,buf);
return 1;
}
int AddCC(char *number)
{
char bufcc[32],buf[BUFSIZE];
char CC[32];
PutLogFunID("AddCC");
xap_get_cc((u8 *)CC);
BcdToAscii(bufcc, (BYTE *)CC,4);
StringCut(bufcc,'E');
strcpy(buf,bufcc);
strcat(buf,number);
strcpy(number,buf);
return 1;
}
int AddInterPrefix(char *number)
{
char inter_prefix[32];
char bufi[32];
char buf[32];
PutLogFunID("AddInterPrefix");
xap_get_interprefix((u8 *)inter_prefix);
BcdToAscii(bufi, (BYTE *)inter_prefix,4);
StringCut(bufi,'E');
strcpy(buf,number);
sprintf(number,"%s%s",bufi,buf);
return 1;
}
int AddNationalPrefix(char *number)
{
char national_prefix[32];
char bufn[32];
char buf[32];
PutLogFunID("AddNationalPrefix");
xap_get_nationalprefix((u8 *)national_prefix);
BcdToAscii(bufn, (BYTE *)national_prefix,4);
StringCut(bufn,'E');
strcpy(buf,number);
sprintf(number,"%s%s",bufn,buf);
return 1;
}
int CutUnknownPrefix(char *number)
{
char buf[BUFSIZE],buf1[BUFSIZE];
//char idd_prefix[4], bufi[8];
//char *offset = NULL;
PutLogFunID("CutUnknownPrefix");
if(number == NULL)
return 0;
if(strlen(number)>MAX_ASCII_NUMBER_LEN)
{
pps_print_error(0,
"CutUnknowPrefix src number %s is too long",number);
return 0;
}
strcpy(buf,number);
if(msisdnUnkToInt(buf,buf1)<=0)
return 0;
/*
xap_get_interprefix(idd_prefix);
BcdToAscii(bufi,idd_prefix,4);
StringCut(bufi,'E');
if((offset = strstr(bufi, buf1)) != NULL)
strcpy(buf, offset);
else
strcpy(buf, buf1);
*/
strcpy(buf, buf1);
if(strlen(buf)>MAX_ASCII_NUMBER_LEN)
{
pps_print_error(0,
"CutUnknowPrefix manimpulated number %s is too long",buf);
return 0;
}
strcpy(number, buf);
return 1;
}
int CheckWetherHPLMNUser(char *number)
{
char bufcc[32],buf[BUFSIZE],bufndc[32];
char CC[32],NDC[32];
int len;
PutLogFunID("CheckWetherHPLMNUser");
xap_get_cc((u8 *)CC);
BcdToAscii(bufcc, (BYTE *)CC,4);
StringCut(bufcc,'E');
xap_get_ndc((u8 *)NDC);
BcdToAscii(bufndc, (BYTE *)NDC,6);
StringCut(bufndc,'E');
strcpy(buf,bufcc);
strcat(buf,bufndc);
len = strlen(buf);
if(strncasecmp(buf,number,len)==0)
return 1;
return 0;
}
int CheckSeriveIdentification(char *serviceID,char *servicePWD,u_long srcip,
int *result,char *cause)
{
int loop;
PutLogFunID("CheckSeriveIdentification");
*result = 0;
sprintf(cause,"error service ID");
for(loop=0;loop<MaxThirdPartyInfoItem;loop++)
{
if(memcmp(serviceID,
ppsParam.ppsTables.thirdPartyInfo[loop].serviceID,
strlen(serviceID))==0)
{
if(memcmp(servicePWD,
ppsParam.ppsTables.thirdPartyInfo[loop].servicePassword,
strlen(servicePWD))==0)
{
*result = 1;
sprintf(cause," ");
break;
}
else
sprintf(cause,"error password");
}
}
return *result;
}
int cliManipulationFunction(char *caller, char *called) /* only support IDD string, no prop 91 digits */
/* caller=8675590123, called=86755234 */
{
char tmpCaller[64],tmpCalled[64];
if(caller == NULL || called == NULL)
return 0;
if(strlen(caller)>MAX_MSISDN_ALEN || strlen(called)>MAX_MSISDN_ALEN)
return 0;
sprintf(tmpCaller,"91%s",caller);
sprintf(tmpCalled,"91%s",called);
cliUptoCalled(tmpCaller,tmpCalled);
if(strlen(tmpCaller)>MAX_MSISDN_ALEN)
return 0;
strcpy(caller,&tmpCaller[2]);
return strlen(caller);
}
int ppsCheckMTSMSCharging(char *msisdn)
{
_account_info account_info;
if(msisdn == NULL) return 1;
if(strlen(msisdn)>=23) return 1;
strcpy((char *)account_info.number, msisdn);
if( !GetAccountPos(&account_info)) return 1;
account_info.cos_id = GetAccountCosID(&account_info);
if(ppsParam.ppsTables.cosTable[account_info.cos_id].serviceControl[0].mtSMSCharge)
{
if(GetAccountBalance(account_info.head, account_info.tail)>=
ppsParam.ppsTables.cosTable[account_info.cos_id].serviceControl[0].mtSMSCharge)
return 1;
else
return 0;
}
return 1;
}
int pps_get_ro_voice_quota(_state_data *shmp)
{
int retval = 0;
if(shmp->process_info.tariff_flag == 0)
return 0;
if(shmp->caller_info.status != T_NORMAL)
return 0;
if(GetExpiration(&shmp->caller_info) < tvnow.tv_sec)
return 0;
retval = GetMaxCallDuration(shmp);
return retval;
}
static int pps_update_last_ro_quota_type(_state_data *shmp, u_char new_type, u32 new_quota)// for Ro refund
{
if (shmp->process_info.ro_if.last_ro_quota_type == 0)// bundle
{
if (new_type == 0)// bundle
{
shmp->process_info.ro_if.last_bundle_duration += new_quota;
}
else
{
shmp->process_info.ro_if.last_cap_duration = new_quota;
shmp->process_info.ro_if.last_ro_quota_type = 1;
}
}
else
{
if (new_type == 0)// bundle
{
shmp->process_info.ro_if.last_bundle_duration = new_quota;
shmp->process_info.ro_if.last_ro_quota_type = 0;
}
else
{
shmp->process_info.ro_if.last_cap_duration += new_quota;
}
}
return 0;
}
// need_assigned_duration: Param IN and OUT; new_assigned_bundle, Param OUT;
float pps_billing_ro_voice(_state_data *shmp, u32 *assigned_duration, u32 *new_assigned_bundle)
{
float charge = 0.0, balance = 0.0;
_bill_tariff *bt_ptr;
int discount, left_bundle, left_duration_to_assign = 0;
bt_ptr = &shmp->process_info.tariff;
discount = GetDiscount(tvnow.tv_sec, bt_ptr->discountID);
if(shmp->process_info.serviceType == SRV_NORMAL_MO_CALL ||
shmp->process_info.serviceType == SRV_NORMAL_MF_CALL) // Get left bundle
{
left_bundle = pps_get_account_bundle_mo_voice(shmp);
balance = GetAccountBalance(shmp->caller_info.head, shmp->caller_info.tail);
}
else
{
left_bundle = pps_get_account_bundle_mt_voice(shmp);
balance = GetAccountBalance(shmp->called_info.head, shmp->called_info.tail);
}
// allocation of the first time
if (shmp->process_info.chargedTime == 0)
{
if (left_bundle > 0)
{
// allocate bunle first, and then balance
if (left_bundle >= *assigned_duration)// enough bundle for first quota
{
*new_assigned_bundle = *assigned_duration;
pps_update_last_ro_quota_type(shmp, 0, *new_assigned_bundle);
goto out;
}
else
{
*new_assigned_bundle = left_bundle;
pps_update_last_ro_quota_type(shmp, 0, *new_assigned_bundle);
left_duration_to_assign = *assigned_duration - left_bundle;// have to allocate by balance to meet this quota
*assigned_duration = left_bundle;
}
}
else
{
// check if balance enough for the min charge unit
if(bt_ptr->unit_time == 0 || bt_ptr->mini_unit == 0)// error param, can't allocate duratioon
{
*assigned_duration = 0;
pps_update_last_ro_quota_type(shmp, 1, 0);
goto out;
}
charge = (bt_ptr->mini_unit * 1.0 * ( bt_ptr->tierRating.rating[0].base_fee + bt_ptr->tierRating.rating[0].long_distance_fee)) * discount / 100.0;
charge += bt_ptr->adjustment;
if (charge <= balance)// have enough balance for the first basic charge
{
int basic_time = (bt_ptr->mini_unit * bt_ptr->unit_time) + bt_ptr->free_time;
if (basic_time >= *assigned_duration)// basic time is enough for this quota
{
*assigned_duration = basic_time;
pps_update_last_ro_quota_type(shmp, 1, 0);// basic time don't have to refund
goto out;
}
else
{
left_duration_to_assign = *assigned_duration - basic_time;// have to allocate more by balance to meet this quota
*assigned_duration = basic_time;
pps_update_last_ro_quota_type(shmp, 1, 0);// basic time don't have to refund
}
}
else
{
*assigned_duration = 0;
pps_update_last_ro_quota_type(shmp, 1, 0);
goto out;
}
}
}
else
{
if (left_bundle > 0)
{
// allocate bunle first, and then balance
if (left_bundle >= *assigned_duration)// enough bundle for first quota
{
*new_assigned_bundle = *assigned_duration;
pps_update_last_ro_quota_type(shmp, 0, *new_assigned_bundle);
goto out;
}
else
{
*new_assigned_bundle = left_bundle;
pps_update_last_ro_quota_type(shmp, 0, *new_assigned_bundle);
left_duration_to_assign = *assigned_duration - left_bundle;// have to allocate by balance to meet this quota
*assigned_duration = left_bundle;
}
}
else
{
int units = 0;
// calculate how many unit have to allocate
units = (*assigned_duration + bt_ptr->unit_time -1) / bt_ptr->unit_time;
// check if balance enough for the min charge unit
charge = (units * 1.0 * ( bt_ptr->tierRating.rating[0].base_fee + bt_ptr->tierRating.rating[0].long_distance_fee)) * discount / 100.0;
if (charge <= balance)// have enough balance for the first basic charge
{
*assigned_duration = units * bt_ptr->unit_time;
pps_update_last_ro_quota_type(shmp, 1, *assigned_duration);
goto out;
}
else// have no enough balance, so that assign as much unit as it could
{
units = balance / ((1.0 * ( bt_ptr->tierRating.rating[0].base_fee + bt_ptr->tierRating.rating[0].long_distance_fee)) * discount / 100.0);
if (units > 0)
{
charge = (units * 1.0 * ( bt_ptr->tierRating.rating[0].base_fee + bt_ptr->tierRating.rating[0].long_distance_fee)) * discount / 100.0;
*assigned_duration = units * bt_ptr->unit_time;
pps_update_last_ro_quota_type(shmp, 1, *assigned_duration);
}
else
{
*assigned_duration = 0;
}
goto out;
}
}
}
//
// have to allocate more quota by balance
if (left_duration_to_assign > 0)
{
int units = 0;
float temp_charge = 0.0;
// calculate how many unit have to allocate
units = (left_duration_to_assign + bt_ptr->unit_time -1) / bt_ptr->unit_time;
// check if balance enough for the min charge unit
temp_charge = (units * 1.0 * ( bt_ptr->tierRating.rating[0].base_fee + bt_ptr->tierRating.rating[0].long_distance_fee)) * discount / 100.0;
if ((temp_charge + charge) <= balance)// have enough balance for the first basic charge
{
charge += temp_charge;
*assigned_duration += units * bt_ptr->unit_time;
pps_update_last_ro_quota_type(shmp, 1, units * bt_ptr->unit_time);
goto out;
}
else// have no enough balance, so that assign as much unit as it could
{
units = (balance - charge) / ((1.0 * ( bt_ptr->tierRating.rating[0].base_fee + bt_ptr->tierRating.rating[0].long_distance_fee)) * discount / 100.0);
if (units > 0)
{
charge += (units * 1.0 * ( bt_ptr->tierRating.rating[0].base_fee + bt_ptr->tierRating.rating[0].long_distance_fee)) * discount / 100.0;
*assigned_duration += units * bt_ptr->unit_time;
pps_update_last_ro_quota_type(shmp, 1, units * bt_ptr->unit_time);
}
goto out;
}
}
//
if(0)
DebugMsg(debugmib.display.asciiOut, " %s:%d , tariff: unit=%d, %.2f+%.2f, assigned_duration=%d, , discount=%d ,charge=%.2f",
__FUNCTION__, __LINE__,
bt_ptr->unit_time ,
bt_ptr->tierRating.rating[0].base_fee,
bt_ptr->tierRating.rating[0].long_distance_fee,
*assigned_duration,
discount,
charge
);
out:
shmp->process_info.chargedTime ++;
return charge;
}
float pps_billing_ro_voice_with_crm(_state_data *shmp, u32 *assigned_duration, u32 *new_assigned_bundle)
{
float charge = 0.0, balance = 0.0;
int discount, left_bundle, left_duration_to_assign = 0;
discount = shmp->process_info.rest_if.tariff_discount;
left_bundle = shmp->process_info.rest_if.total_plan_value - shmp->process_info.rest_if.used_plan_value;
if(shmp->process_info.serviceType == SRV_NORMAL_MO_CALL ||
shmp->process_info.serviceType == SRV_NORMAL_MF_CALL)
{
balance = GetAccountBalance(shmp->caller_info.head, shmp->caller_info.tail);
}
else
{
balance = GetAccountBalance(shmp->called_info.head, shmp->called_info.tail);
}
// allocation of the first time
if (0)//(shmp->process_info.chargedTime == 0)
{
if (left_bundle > 0)
{
// allocate bunle first, and then balance
if (left_bundle >= *assigned_duration)// enough bundle for first quota
{
*new_assigned_bundle = *assigned_duration;
pps_update_last_ro_quota_type(shmp, 0, *new_assigned_bundle);
goto out;
}
else
{
*new_assigned_bundle = left_bundle;
pps_update_last_ro_quota_type(shmp, 0, *new_assigned_bundle);
left_duration_to_assign = *assigned_duration - left_bundle;// have to allocate by balance to meet this quota
*assigned_duration = left_bundle;
}
}
else
{
// check if balance enough for the min charge unit
if(shmp->process_info.rest_if.unit == 0)// error param, can't allocate duratioon
{
*assigned_duration = 0;
pps_update_last_ro_quota_type(shmp, 1, 0);
goto out;
}
charge = ((*assigned_duration / shmp->process_info.rest_if.unit) * 1.0 * ( shmp->process_info.rest_if.unit_charge)) * discount / 100.0;
if (charge <= balance)// have enough balance for the first basic charge
{
pps_update_last_ro_quota_type(shmp, 1, 0);// basic time don't have to refund
goto out;
}
else
{
if (balance >= shmp->process_info.rest_if.unit_charge)// last unit?
{
charge = balance;
*assigned_duration = shmp->process_info.rest_if.unit;
pps_update_last_ro_quota_type(shmp, 1, 0);
goto out;
}
else
{
*assigned_duration = 0;
pps_update_last_ro_quota_type(shmp, 1, 0);
goto out;
}
}
}
}
else
{
if (left_bundle > 0)
{
// allocate bunle first, and then balance
if (left_bundle >= *assigned_duration)// enough bundle for first quota
{
*new_assigned_bundle = *assigned_duration;
pps_update_last_ro_quota_type(shmp, 0, *new_assigned_bundle);
goto out;
}
else
{
*new_assigned_bundle = left_bundle;
pps_update_last_ro_quota_type(shmp, 0, *new_assigned_bundle);
left_duration_to_assign = *assigned_duration - left_bundle;// have to allocate by balance to meet this quota
*assigned_duration = left_bundle;
}
if((logMsgFlag & 0x04) || (logMsgFlag & 0x02) || shmp->process_info.logMsisdn)
DebugMsg(debugmib.display.asciiOut, " %s:%d, left bundle[%d], assigned=[%d], need assigned by balance=[%d]",
__FUNCTION__, __LINE__,
left_bundle,
*assigned_duration,
left_duration_to_assign
);
}
else
{
int units = 0;
// calculate how many unit have to allocate
units = (*assigned_duration + shmp->process_info.rest_if.unit -1) / shmp->process_info.rest_if.unit;
// check if balance enough for the min charge unit
charge = (units * 1.0 * ( shmp->process_info.rest_if.unit_charge)) * discount / 100.0;
if (charge <= balance)// have enough balance for the first basic charge
{
*assigned_duration = units * shmp->process_info.rest_if.unit;
pps_update_last_ro_quota_type(shmp, 1, *assigned_duration);
goto out;
}
else// have no enough balance, so that assign as much unit as it could
{
units = balance / ((1.0 * ( shmp->process_info.rest_if.unit_charge)) * discount / 100.0);
if (units > 0)
{
charge = (units * 1.0 * (shmp->process_info.rest_if.unit_charge)) * discount / 100.0;
*assigned_duration = units * shmp->process_info.rest_if.unit;
pps_update_last_ro_quota_type(shmp, 1, *assigned_duration);
}
else
{
*assigned_duration = 0;
charge = 0.0;
}
if((logMsgFlag & 0x04) || (logMsgFlag & 0x02) || shmp->process_info.logMsisdn)
DebugMsg(debugmib.display.asciiOut, " %s:%d, no enough balance: units[%d], assigned=[%d], balance=%.2f, charge=%.2f",
__FUNCTION__, __LINE__,
units,
*assigned_duration,
balance, charge
);
goto out;
}
}
}
//
// have to allocate more quota by balance
if (left_duration_to_assign > 0)
{
int units = 0;
float temp_charge = 0.0;
// calculate how many unit have to allocate
units = (left_duration_to_assign + shmp->process_info.rest_if.unit -1) / shmp->process_info.rest_if.unit;
// check if balance enough for the min charge unit
temp_charge = (units * 1.0 * ( shmp->process_info.rest_if.unit_charge)) * discount / 100.0;
if ((temp_charge + charge) <= balance)// have enough balance for the first basic charge
{
charge += temp_charge;
*assigned_duration += units * shmp->process_info.rest_if.unit;
pps_update_last_ro_quota_type(shmp, 1, units * shmp->process_info.rest_if.unit);
goto out;
}
else// have no enough balance, so that assign as much unit as it could
{
units = (balance - charge) / ((1.0 * ( shmp->process_info.rest_if.unit_charge)) * discount / 100.0);
if (units > 0)
{
charge += (units * 1.0 * ( shmp->process_info.rest_if.unit_charge)) * discount / 100.0;
*assigned_duration += units * shmp->process_info.rest_if.unit;
pps_update_last_ro_quota_type(shmp, 1, units * shmp->process_info.rest_if.unit);
}
goto out;
}
}
//
out:
if((logMsgFlag & 0x04) || (logMsgFlag & 0x02) || shmp->process_info.logMsisdn)
DebugMsg(debugmib.display.asciiOut, " %s:%d, tariff: unit=%d*%.2f, assigned/bundle/cap=[%d/%d/%d], discount=%d, charge=%.2f",
__FUNCTION__, __LINE__,
shmp->process_info.rest_if.unit,
shmp->process_info.rest_if.unit_charge,
*assigned_duration, *new_assigned_bundle, left_duration_to_assign,
discount,
charge
);
shmp->process_info.chargedTime ++;
return charge;
}
float pps_refund_ro_voice_with_crm(_state_data *shmp, u32 refund_duration, u32 *refund_bundle)
{
float charge = 0.0;
u32 bundle_duration = 0, cap_duration = 0;
int discount;
discount = shmp->process_info.rest_if.tariff_discount;
if (shmp->process_info.ro_if.last_ro_quota_type == 0)// bundle
{
if (refund_duration <= shmp->process_info.ro_if.last_bundle_duration)
{
// all refund to bundle
bundle_duration = refund_duration;
}
else
{
bundle_duration = shmp->process_info.ro_if.last_bundle_duration;
cap_duration = refund_duration - bundle_duration;
}
}
else
{
if (refund_duration <= shmp->process_info.ro_if.last_cap_duration)
{
// all refund to balance
cap_duration = refund_duration;
}
else
{
cap_duration = shmp->process_info.ro_if.last_cap_duration;
bundle_duration = refund_duration - cap_duration;
}
}
*refund_bundle = bundle_duration;
if ((shmp->process_info.rest_if.unit > 0) && (cap_duration >= shmp->process_info.rest_if.unit))
{
int units = 0;
units = cap_duration / shmp->process_info.rest_if.unit;
charge = (units * 1.0 * ( shmp->process_info.rest_if.unit_charge)) * discount / 100.0;
}
return charge;
}
float pps_refund_ro_voice(_state_data *shmp, u32 refund_duration, u32 *refund_bundle)
{
float charge = 0.0;
_bill_tariff *bt_ptr;
u32 bundle_duration = 0, cap_duration = 0;
int discount;
bt_ptr = &shmp->process_info.tariff;
discount = GetDiscount(tvnow.tv_sec, bt_ptr->discountID);
if (shmp->process_info.ro_if.last_ro_quota_type == 0)// bundle
{
if (refund_duration <= shmp->process_info.ro_if.last_bundle_duration)
{
// all refund to bundle
bundle_duration = refund_duration;
}
else
{
bundle_duration = shmp->process_info.ro_if.last_bundle_duration;
cap_duration = refund_duration - bundle_duration;
}
}
else
{
if (refund_duration <= shmp->process_info.ro_if.last_cap_duration)
{
// all refund to balance
cap_duration = refund_duration;
}
else
{
cap_duration = shmp->process_info.ro_if.last_cap_duration;
bundle_duration = refund_duration - cap_duration;
}
}
*refund_bundle = bundle_duration;
if (bt_ptr->unit_time == 0)
{
bt_ptr->unit_time = 60;
}
if (cap_duration >= bt_ptr->unit_time)
{
int units = 0;
units = cap_duration / bt_ptr->unit_time;
charge = (units * 1.0 * ( bt_ptr->tierRating.rating[0].base_fee + bt_ptr->tierRating.rating[0].long_distance_fee)) * discount / 100.0;
}
return charge;
}
/*-----------CRM related functions --------------------------------*/
int pps_update_user_info_for_crm_create_account(_prepaid_info *user_ptr,
int customer_id, int account_id, int product_id, int plan_id, int balance, int expiry_day, int rent_charge, int birthday, int cug_id)
{
if(user_ptr == NULL)
return 0;
#ifdef OCS_WITH_CRM
user_ptr->balance = balance;
user_ptr->mo_expiration_date = user_ptr->mt_expiration_date = expiry_day;
user_ptr->crm_info.customer_id = customer_id;
user_ptr->crm_info.account_id = account_id;
user_ptr->crm_info.product_id = product_id;
user_ptr->crm_info.base_plan_id = plan_id;
user_ptr->crm_info.rent_charge = rent_charge;
user_ptr->crm_info.birthday = birthday;
user_ptr->cug_id = cug_id;
user_ptr->status = T_NORMAL;
#endif
return 1;
}