/* for daily report 
 * includes: cdr , account, repaid card
*/

#include "../include/includes.h"
#include "../include/report.h"
#include "../include/ramdata.h"
#include "../include/ppsm.h"
#include "../include/cdrme.h"
#include "../include/param.h"
#include "../include/precard.h"
#include "../include/message.h"
#include "../include/plat_inc.h"

_pps_report			pps_report;

extern u_long		PPS_OID_PREFIX[];
extern u_long		peer_server_ip;
extern char			masterFlag;
/*------------------------------------------------*/

extern int          time_now[7];
extern _ram_data    *ramshm_ptr;
extern struct		timeval tvnow;
extern _state_machine *smshm_ptr;
extern	PPSParamStruct	ppsParam;
/*------------------------------------------------*/
char call_type_name[16][32]={
"LOCAL_CALL_OUT",
"IDD_CALL",
"NDD_CALL",
"INCOMING_CALL",
"RENT_CHARGE",
"AST_RECHARGE",
"AST_CHARGE",
"RECHARGE_SUC",
"RECHARGE_FAIL",
"SHORT_MESSAGE"
};

extern int	GetCardIndex();
int		GetDailyReportByIndex(u_char oidLen, DWORD *oid, 
				u_char *pdata, BYTE *vartype);
int		printfDailyLog(int index);
extern u_long	LOCAL_IP;
static	int	waittime = 0, retrytime = 0, getDailyReportResponseFlag = 0;
/*------------------------------------------------*/
int ClearCleanUsedCardForDailyReport(int index);
int GetPrecardSumData(int index, int type);
int	LoadDailyReport();
int	ReadDailyReportFromPeerServer();
int	AccountExpiredDateCheck();
int	SendDailyReportToPeerServerForStop();
extern void SendOperatorRechargeCDR();
extern int  IsPromotionTime(COSTable *cosTableItem, struct timeval tvn);
extern int  smppSendAccountInfo();
extern int  smppSendMOSM(char *called, char *caller, u_char *msg,int msgLen,u_char dataCoding);
extern int CleanPPSUSSDStatisticsByDay();
extern 	void resetPoolSlaveDaily(u_short head,u_short tail);
extern int UseExternalVC();
extern u_char *getSmsSentenceNative(u8 languageType,SMS_SENTENCE	id);
extern int subscribe_bundle_plan_send_used_up_info(char *caller_number, SMS_SENTENCE id);
extern char* ppsParseSentence(char *sentence, int varNum, char *varStr[]);
/*----------------------------------------------*/
void reportInit()
{
	PutLogFunID("reportInit");

	pps_report.ptrTail = 0;
	memset(&pps_report,0,sizeof(_pps_report));

	getnowtime(time_now);
	pps_report.ptrTail = time_now[6]; /* week day */
	pps_report.saveHead = pps_report.ptrTail;
	pps_report.saveTail = pps_report.ptrTail;

	pps_report.daily_report[pps_report.ptrTail].year_month_day[0]=time_now[0];
	pps_report.daily_report[pps_report.ptrTail].year_month_day[1]=time_now[1];
	pps_report.daily_report[pps_report.ptrTail].year_month_day[2]=time_now[2];

	LoadDailyReport();
}

void DisplayDailyReportIndex(char *ptr)
{
	ptr = (char *)&pps_report.ptrTail;
}

int reportCreatedDaily()
{   
	static int dailyState=0;
	static int segmentno=0;
	int	balance;
   
	PutLogFunID("reportCreatedDaily");
	
	switch(dailyState){
		case 0:
	  		if(time_now[3]==0 && time_now[4]==0 && time_now[5]<5) //00:00:00
			if(time_now[5]>3)
			{
				dailyState = 1;  
				segmentno = 0;
				CleanPPSUSSDStatisticsByDay();
			}
		break;
		case 1:
		//if(segmentno<1)
		{
			reportAccount(segmentno);
			reportPrepaidCard(segmentno);
			segmentno++;
		}
		//else
		{
			segmentno = 0;
			dailyState = 2;
			waittime = 0;
			retrytime = 0;
		}
		break;
		case 2:
			dailyState = 3;
			waittime = 0;
			getDailyReportResponseFlag = 0;
			ReadDailyReportFromPeerServer();
		break;
		case 3:
			if(!getDailyReportResponseFlag)
			{
				if(waittime++>10)
				{
					if(retrytime++<2)
					{
						waittime = 0;
						dailyState = 2;
					}
					else
					{
						waittime = 0;
						retrytime = 0;
						dailyState = 4;
					}
				}
			}
			else
				dailyState = 4;
		break;
 		case 4:
			balance =  
				(int)pps_report.daily_report[pps_report.ptrTail].balance_summary.today_recharge;
			debugmib.report_sum[pps_report.ptrTail][1] = balance;
  			balance = 
				(int)pps_report.daily_report[pps_report.ptrTail].balance_summary.today_charge;
 			debugmib.report_sum[pps_report.ptrTail][3] = balance; 
			
			pps_report.ptrTail = time_now[6];
			pps_report.ptrTail %=MAX_RECORDS_SAVED;
			memset(&pps_report.daily_report[pps_report.ptrTail],0,sizeof(_daily_report));
			pps_report.daily_report[pps_report.ptrTail].year_month_day[0]=time_now[0];
			pps_report.daily_report[pps_report.ptrTail].year_month_day[1]=time_now[1];
 			pps_report.daily_report[pps_report.ptrTail].year_month_day[2]=time_now[2];

			pps_report.saveTail ++;

			if(pps_report.saveTail ==0x80000000){
				pps_report.saveTail = 0;
			}
			if(pps_report.saveTail == pps_report.saveHead){
				pps_report.saveHead ++;
				pps_report.saveHead %=0x80000000;
			}
			dailyState = 5;
			segmentno = 0;
		break;
		case 5:
			if(segmentno ++>(20*CYCLE_STATE_INTERVAL))
			{
				dailyState = 0;
				segmentno = 0;
			}
		break;
		default:
			dailyState = 0;
			segmentno = 0;
		break;
	}
	AccountExpiredDateCheck();
	return 1;
}

int reportCDRIncrement(int calltype, int duration, float charge,ulong gprsVolume)
{
	int type=0,index=0;

	PutLogFunID("reportCDRIncrement");

	switch(calltype){
	   case CT_LOCAL_CALL_OUT:
	   case CT_TRUNK_CALL_OUT:
	     type = LOCAL_CALL_OUT;
	   break;
	   case CT_LOCAL_CALL_IN:
	   case CT_TRUNK_CALL_IN:
	     type = INCOMING_CALL;
	   break;
	   case CT_NDD_CALL_OUT:
	     type = NDD_CALL;
	   break;
	   case CT_IDD_CALL_OUT:
	     type = IDD_CALL;
	   break;
	   case CT_PERIODIC_CHARGE:
	     type = RENT_CHARGE;
	   break;
	   case CT_ASSISTED_UP:
	   	 type = AST_RECHARGE;
	   break;
	   case CT_ASSISTED_DOWN:
	   	 type = AST_CHARGE;
	   break;
	   case CT_RECHARGE_SUCCESS:
	   	 type = RECHARGE_SUC;
	//	 return 0;
	   break;
	   case CT_RECHARGE_FAIL:
	   	 type = RECHARGE_FAIL;
		 return 0;
	   break;
	   case CT_MO_SM:
	   	 type = SHORT_MESSAGE;
	   break;
	   case CT_CONFERENCE_CALL:
	     type = CONFERENCE_CALL;
	   break;
	   case CT_THIRD_PARTY_CHARGE:
		 type = SERVICE_CHARGE;
	   break;
	   case CT_BUNDLE_PLAN_CHARGE:
	   	type = RENT_CHARGE;
	   break;
	   default:
		return 0;
	   break;
	}
	index = pps_report.ptrTail;

	pps_report.daily_report[index].call_report.call_record[type].call_type = type;
   	if(type !=RECHARGE_SUC)
	{
		pps_report.daily_report[index].call_report.call_record[type].call_times ++;
		pps_report.daily_report[index].call_report.call_record[type].call_duration += duration;
		pps_report.daily_report[index].call_report.call_record[type].call_charge += charge; 
		pps_report.daily_report[index].call_report.total_call_num ++;
		pps_report.daily_report[index].call_report.total_call_duration  +=duration;
	}
	
	if(type == RECHARGE_SUC || type== AST_RECHARGE){
		pps_report.daily_report[index].balance_summary.today_recharge = 
		pps_report.daily_report[index].balance_summary.today_recharge + charge; 
	}
	else
	{
		pps_report.daily_report[index].balance_summary.today_charge += charge;
		pps_report.daily_report[index].call_report.total_call_charge  += charge;
	}
	
	return 1;
}

int reportAccount(int segmentno)
{
	int				i,j,index,for_index,cos_id=0;
	int				balance;
	double			totalBalance=0;

	u_short			status=0;
	_prepaid_info  	*shmp=NULL;
	COSTable		*cosTableItem;

	PutLogFunID("reportAccount");
	
	index = pps_report.ptrTail;
	
//	for(i=segmentno*100;i<(segmentno+1)*100;i++)
	for(i=0;i<MSISDN_HEAD_NUM;i++)
	{
		for(j=0;j<UNIT_STORE_ACCOUNT;j++)
		{
			shmp = &ramshm_ptr->prepaid_data.prepaid_info[i][j];
			if(shmp->msisdn[9]>2)
			{
				status = shmp->status;
				shmp->free_sm_counter = 0;
				shmp->gprsNotificationTimes = 0;

				if(OCS_with_external_CRM())
				{
					//rent chage for CUG service
					if(shmp->cug_id != NOT_CUG_ACCOUNT && shmp->crm_info.vas_cug_state == 0)
					{
						pps_send_rent_charge_to_crm(i, j);					
					}
				}
				
				pps_report.daily_report[index].account_report.total_num ++;
				pps_report.daily_report[index].account_report.total_balance =
				totalBalance = totalBalance +
								shmp->balance +
								shmp->promo_balance;
				pps_report.daily_report[index].account_report.user_num[status]++;
				
				cos_id = shmp->cos_id%MaxCosTableItem;
				cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
				if(cosTableItem->tariff[0].capPlanResetDay == time_now[2] || cosTableItem->tariff[0].capPlanResetDay==0) 
					/*reset day=0 means CAP is daily based*/
				{
						
					shmp->in_net_cap_sms_balance = 0;
					shmp->in_net_cap_sms_counter = 0;
					shmp->out_net_cap_sms_balance = 0;
					shmp->out_net_cap_sms_counter = 0;
					
					shmp->in_net_cap_balance = 0;
					shmp->out_net_cap_balance = 0;
					
					shmp->in_net_cap_call_balance = 0;
					shmp->in_net_cap_call_duration = 0;
					shmp->out_net_cap_call_balance = 0;
					shmp->out_net_cap_call_duration = 0;	

					shmp->gprsBalance = 0;
					shmp->gprsVolume = 0;
					shmp->gprsVolumeThisMonth = 0;

					shmp->cap_sms_notify_counter = 0;
				}				
				/*
				if(shmp->bundle_info.validity_date < tvnow.tv_sec)
				{
					memset(&shmp->bundle_info, 0x00, sizeof(_bundle_info));
				}
				*/
			}
		}
	}
	pps_report.daily_report[index].account_report.total_balance = 
			totalBalance;
	balance =
			(int)pps_report.daily_report[index].account_report.total_balance;	
	debugmib.report_sum[index][2] = balance; 
	
	for_index = (index+6)%7;
	balance = 
		(int)pps_report.daily_report[for_index].account_report.total_balance;
	debugmib.report_sum[index][0] = balance;

	return 1;
}

int reportPrepaidCard(int segmentno)
{
	int		i,j;
	int		index=0,update_day=0,now_day=0;
	long	face_value;

	_prepaid_card_report *shmp=NULL;

	PutLogFunID("reportPrepaidCard");
	
	if(UseExternalVC())
		return 1;

	if(OCS_with_external_CRM())
		return 1;

	now_day = (tvnow.tv_sec - timezone)/(24*3600);

  	for(i=0;i<MAX_CARD_SEGMENT;i++)
	{
		//if (ramshm_ptr->card_data.segment_used_flag[i] == 0)
		//{
		//	continue;
		//}
		for(j=0;j<MAX_CARD_NUM_PSEG;j++)
		{
			if(ramshm_ptr->card_data.prepaid_card[i][j].card_no[MAX_CARD_LENGTH]>0)
			{
				face_value = ramshm_ptr->card_data.prepaid_card[i][j].face_value;
				index = GetCardIndex(face_value);
				if(index<0) continue;

				shmp = &pps_report.daily_report[pps_report.ptrTail].prepaid_card_report;
				shmp->face_value[index] = face_value;
		

				if(ramshm_ptr->card_data.prepaid_card[i][j].card_status == CARD_FRESH ||
					ramshm_ptr->card_data.prepaid_card[i][j].card_status == CARD_SUSPEND)
				{
					shmp->unused[index]++;
					if(ramshm_ptr->card_data.prepaid_card[i][j].expiry_date<tvnow.tv_sec)
					{
						shmp->unused[index]--;
						shmp->used_today[index]++;
						MoveUsedCardToBuffer(i*MAX_CARD_NUM_PSEG+j);
					}
				}
				else if(ramshm_ptr->card_data.prepaid_card[i][j].card_status == CARD_USED)
				{
					shmp->total_used[index]++;
					update_day = (ramshm_ptr->card_data.prepaid_card[i][j].updated_date - timezone)/(24*3600);
					if(now_day==(update_day+1))
					{
						shmp->used_today[index]++;
					}
					else 
					{
						MoveUsedCardToBuffer(i*MAX_CARD_NUM_PSEG+j);
					}
				}/* else  */
			}/* if */
		}/* for j */
	}/* for i */
	return 1;
}

#ifdef _ZED_NO_CALLER_NUM_AND_EXPIRY_DATE_ // ussd_code daily report
extern int yx_ussd_daily_report;
int GetUssdCodeDailyReportByIndex(u_char oidLen,DWORD *oid, 
				u_char *pdata, BYTE *vartype)
{
    int  totalLen;
    int  index,saveIndex;//,yesterdayIndex;
	int  value=0,tag;
	char buf[256]="",tagbuf[16]="";
    _daily_report *shmp=NULL, *shmp_peer = NULL;
    ASN_BUF       *asnbuf, asnbuf1;

	PutLogFunID("GetUssdCodeDailyReportByIndex");
    asnbuf = &asnbuf1;
    AsnEncode(pdata,512,asnbuf);

	index = oid[14];
	saveIndex = index %7;
	//yesterdayIndex = (saveIndex+7-1)%7;

    shmp = &pps_report.daily_report[saveIndex];
    shmp_peer = &pps_report.peer_daily_report[saveIndex];

	sprintf(buf,"%04d-%02d-%02d",
			shmp->year_month_day[0],
			shmp->year_month_day[1],
			shmp->year_month_day[2]);
    totalLen = add_tlv("1", 10, (u_char *)buf, 0x80, asnbuf);
    
	PutLogFunID("GetDailyReportByIndex0");

	strcpy(shmp->ussdcode_report[USSDCODE_TYPE_QUERY].code, USSDCODE_QUERY_CODE_STR);
	strcpy(shmp->ussdcode_report[USSDCODE_TYPE_TOPUP].code, USSDCODE_TOPUP_CODE_STR);
	strcpy(shmp->ussdcode_report[USSDCODE_TYPE_HOTLINE].code, USSDCODE_HOTLINE_CODE_STR);

	int i=0, offset=2, tagPerCode=8, codeLen=0;
	for (i=0; i<USSDCODE_MAX_CODE_NUM; i++)
	{
		codeLen = strlen(shmp->ussdcode_report[i].code);
		if (codeLen <= 0)
		{
			continue;
		}
		
		tag = offset + tagPerCode*i;
		sprintf(tagbuf,"%d",tag);
		totalLen = add_tlv(tagbuf, codeLen, (u_char *)shmp->ussdcode_report[i].code,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 1;
	    value = shmp->ussdcode_report[i].req_count;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 2;
	    value = shmp->ussdcode_report[i].req_duration;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 3;
	    value = shmp->ussdcode_report[i].err_timeout_count;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 4;
	    value = shmp->ussdcode_report[i].err_system_count;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 5;
	    value = shmp->ussdcode_report[i].err_msg_count;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
	}
	
	PutLogFunID("GetUssdCodeDailyReportByIndex1");

	//printfDailyLog(saveIndex);
	return totalLen;
}
#endif

int GetDailyReport(u_char oidLen, DWORD *oid, u_char *pdata, BYTE *vartype)
{
   int ptrHead;
   if(oidLen<14) return -1;

	PutLogFunID("GetDailyReport");
	
   switch(oid[13]){
     case 0x01:
	   *vartype = 0x02;
	   ptrHead = pps_report.saveHead;
	   pdata[0] = ptrHead>>24;
	   pdata[1] = ptrHead>>16;
	   pdata[2] = ptrHead>>8;
	   pdata[3] = ptrHead;
	   return 4;
	 break;
	 case 0x02:
	   *vartype = 0x02;
	   ptrHead = pps_report.saveTail;
	   pdata[0] = ptrHead>>24;
	   pdata[1] = ptrHead>>16;
	   pdata[2] = ptrHead>>8;
	   pdata[3] = ptrHead;
	   return 4;
	 break;
	 case 0x03:
	   if(oidLen<15){
	   	 printf("error oid len: %d\n",oidLen);
	   	 return -1;
	   }
	   
   	  // if(!masterFlag) return -1;
	   if(oid[14]>=pps_report.saveTail) return -1;
	   return GetDailyReportByIndex(oidLen,oid,pdata,vartype);
	 break;
#if 0//def _ZED_NO_CALLER_NUM_AND_EXPIRY_DATE_ // ussd_code daily report
	 case 0x04:
	   if(oidLen<15){
	   	 printf("error oid len: %d\n",oidLen);
	   	 return -1;
	   }
	   
   	  // if(!masterFlag) return -1;
	   if(oid[14]>=pps_report.saveTail) return -1;
	   return GetUssdCodeDailyReportByIndex(oidLen,oid,pdata,vartype);
	 break;
#endif
	 default:
	   return -1;
	 break;
   }
   
   return 0;
}

int GetPrepaidCardReport(int index, int valueIndex, int type)
{
    int value=0;
    _daily_report *shmp=NULL;
	
    PutLogFunID("GetPrepaidCardReport");

    if(index<0 || index>=7) return 0;
    if(valueIndex<0 || valueIndex>=MAX_VALUE_TYPE) return 0;
    if(type<0 || type>=3) return 0;
    
    shmp = &pps_report.daily_report[index];

    if(UseExternalVC())
    {
             ClearCleanUsedCardForDailyReport(index);
             value = GetPrecardSumData(valueIndex,type);
    }
    else
    {
        switch(type)
        {
            case 0:
            	  value = shmp->prepaid_card_report.face_value[valueIndex];
            break;
            case 1:
            	  value = shmp->prepaid_card_report.used_today[valueIndex];
            break;
            case 2:
            default:
                value = shmp->prepaid_card_report.unused[valueIndex];		
            break;
        }
    }
    return value;
}

int CountUsedCardForDailyReport(int charge)
{
    int i;

    _prepaid_card_report *ptr;

    ptr = &pps_report.daily_report[pps_report.ptrTail].prepaid_card_report;
    for(i=0;i<MAX_VALUE_TYPE;i++)
    {
        if(ptr->face_value[i] == charge)
        {
            ptr->used_today[i] ++;
            return 1;
        }
    }
    for(i=0;i<MAX_VALUE_TYPE;i++)
    {
        if(ptr->face_value[i] == 0)
        {
            ptr->used_today[i] ++;
            ptr->face_value[i] = charge;
            return 1;
        }
    }
    return 0;
}

int GetDailyReportByIndex(u_char oidLen,DWORD *oid, 
				u_char *pdata, BYTE *vartype)
{
    int  totalLen;
    int  index,saveIndex,i,yesterdayIndex;
	int  value=0,tag,start;
	char buf[256]="",tagbuf[16]="";
	char balancebuf[32]="";// gprsBuf[256]={0};
    _daily_report *shmp=NULL, *shmp_peer = NULL;
	long long	gprsVal;
	u_long			vasVaule;
    ASN_BUF       *asnbuf, asnbuf1;

	PutLogFunID("GetDailyReportByIndex");
    asnbuf = &asnbuf1;
    AsnEncode(pdata,512,asnbuf);

	index = oid[14];
	saveIndex = index %7;
	yesterdayIndex = (saveIndex+7-1)%7;

    shmp = &pps_report.daily_report[saveIndex];
    shmp_peer = &pps_report.peer_daily_report[saveIndex];

	sprintf(buf,"%04d-%02d-%02d",
			shmp->year_month_day[0],
			shmp->year_month_day[1],
			shmp->year_month_day[2]);
    totalLen = add_tlv("1", 10, (u_char *)buf, 0x80, asnbuf);
    
	PutLogFunID("GetDailyReportByIndex0");

	gprsVal = shmp->call_report.gprs_record.gprsCharge + shmp_peer->call_report.gprs_record.gprsCharge+0.5;
	
	for(tag=2;tag<=30;tag++)
    {
	    switch(tag){
		  case 2:
			if(pps_report.daily_report[yesterdayIndex].account_report.total_balance == 0){
			    shmp->balance_summary.yesterday_balance = 
					shmp->account_report.total_balance+
					shmp->balance_summary.today_charge-
					shmp->balance_summary.today_recharge+
					shmp_peer->balance_summary.today_charge-
					shmp_peer->balance_summary.today_recharge;

			}else{
			   shmp->balance_summary.yesterday_balance =	
				pps_report.daily_report[yesterdayIndex].account_report.total_balance;
			}
			sprintf(balancebuf,"%.0f",
					shmp->balance_summary.yesterday_balance);
		  break;
		  case 3:
			sprintf(balancebuf,"%.0f",
					shmp->balance_summary.today_recharge+
					shmp_peer->balance_summary.today_recharge);
		  break;
		  case 4:
			value = shmp->call_report.total_call_charge + 
					shmp_peer->call_report.total_call_charge+
					gprsVal;
			sprintf(balancebuf,"%d",value);
		    /*
			sprintf(balancebuf,"%.0f",
					shmp->balance_summary.today_charge+
					shmp_peer->balance_summary.today_charge);
					*/
		  break;
		  case 5:
		    shmp->balance_summary.today_balance  = 
				shmp->account_report.total_balance;
				/*
			shmp->account_report.total_balance = 
				shmp->balance_summary.today_recharge + 
				shmp->balance_summary.yesterday_balance -
				shmp->balance_summary.today_charge;
				*/
			
			sprintf(balancebuf,"%.0f",shmp->account_report.total_balance);
		  break;
		  case 6:
		    value = shmp->account_report.user_num[0];
		  break;
		  case 7:
		    value = shmp->account_report.user_num[1];
		  break;
		  case 8:
		    value = shmp->account_report.user_num[2];
		  break;
		  case 9:
		    value = shmp->account_report.user_num[3];
		  break;
		  case 10:
		    value = shmp->account_report.user_num[4];
		  break;
		  case 11:
		    value = shmp->account_report.user_num[5];		  	
		  break;
		  case 12:
		    value = shmp->account_report.total_num;
		  break;
		  case 13:
		    value = GetPrepaidCardReport(saveIndex, 0, 0);
		  break;
		  case 14:
		    value = GetPrepaidCardReport(saveIndex, 0, 1);
		  break;
		  case 15:
		    value = GetPrepaidCardReport(saveIndex, 0, 2);
		  break;
		  case 16:
		    value = GetPrepaidCardReport(saveIndex, 1, 0);
		  break;
		  case 17:
		    value = GetPrepaidCardReport(saveIndex, 1, 1);
		  break;
		  case 18:
		    value = GetPrepaidCardReport(saveIndex, 1, 2);
		  break;
		  case 19:
		    value = GetPrepaidCardReport(saveIndex, 2, 0);
		  break;
		  case 20:
		    value = GetPrepaidCardReport(saveIndex, 2, 1);
		  break;
		  case 21:
		    value = GetPrepaidCardReport(saveIndex, 2, 2);
		  break;
		  case 22:
		    value = GetPrepaidCardReport(saveIndex, 3, 0);
		  break;
		  case 23:
		    value = GetPrepaidCardReport(saveIndex, 3, 1);
		  break;
		  case 24:
		    value = GetPrepaidCardReport(saveIndex, 3, 2);
		  break;
		   case 25:
		    value = GetPrepaidCardReport(saveIndex, 4, 0);
		  break;
		  case 26:
		    value = GetPrepaidCardReport(saveIndex, 4, 1);
		  break;
		  case 27:
		    value = GetPrepaidCardReport(saveIndex, 4, 2);
		  break;
		  case 28:
	   	    value = GetPrepaidCardReport(saveIndex, 5, 0);
		  break;
		  case 29:
		    value = GetPrepaidCardReport(saveIndex, 5, 1);
		  break;
		  case 30:
		    value = GetPrepaidCardReport(saveIndex, 5, 2);
		  break;
		  default:
		  break;
      }	   
		sprintf(tagbuf,"%d",tag);
		if(tag<6){
			totalLen = add_tlv(tagbuf, strlen(balancebuf), (u_char *)balancebuf, 0x80, asnbuf);
		}else{
			totalLen = AddInteger(tagbuf,value,0x80,asnbuf);				
		}
   }
   i=0;
  start = 31;
   for(tag=start;tag<(start+12*3);) /* 60 ,2003-10-21 */
   {
	    value = shmp->call_report.call_record[i].call_times + 
				shmp_peer->call_report.call_record[i].call_times;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);				

	    value = shmp->call_report.call_record[i].call_duration + 
				shmp_peer->call_report.call_record[i].call_duration;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);				

	    value = shmp->call_report.call_record[i].call_charge +
				shmp_peer->call_report.call_record[i].call_charge;
		i++;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);				
	}
   	start += 12*3;
	tag = start; /*tag = 67 */
	value = shmp->call_report.total_call_num +
			shmp_peer->call_report.total_call_num;
	sprintf(tagbuf,"%d",tag);
	totalLen = AddInteger(tagbuf,value,0x80,asnbuf);

	tag ++;
	value = shmp->call_report.total_call_duration +
			shmp_peer->call_report.total_call_duration;
	sprintf(tagbuf,"%d",tag);
	totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
	tag ++;
	value = shmp->call_report.total_call_charge + 
			shmp_peer->call_report.total_call_charge + 0.5;
	sprintf(tagbuf,"%d",tag);
	totalLen = AddInteger(tagbuf,value,0x80,asnbuf);

	tag = 70;
	sprintf(tagbuf,"%d",tag);
	gprsVal = shmp->call_report.gprs_record.gprsVolume + shmp_peer->call_report.gprs_record.gprsVolume;
	sprintf(balancebuf,"%lld",gprsVal);
	totalLen = add_tlv(tagbuf, strlen(balancebuf), (u_char *)balancebuf, 0x80, asnbuf);

	tag = 71;
	sprintf(tagbuf,"%d",tag);
	gprsVal = shmp->call_report.gprs_record.gprsDuration + shmp_peer->call_report.gprs_record.gprsDuration;
	sprintf(balancebuf,"%lld",gprsVal);
	totalLen = add_tlv(tagbuf, strlen(balancebuf), (u_char *)balancebuf, 0x80, asnbuf);

	tag = 72;
	sprintf(tagbuf,"%d",tag);
	gprsVal = shmp->call_report.gprs_record.gprsCharge + shmp_peer->call_report.gprs_record.gprsCharge+0.5;
	sprintf(balancebuf,"%lld",gprsVal);
	totalLen = add_tlv(tagbuf, strlen(balancebuf), (u_char *)balancebuf, 0x80, asnbuf);

	/***********************		VAS daily report	**************************/
	tag = 78;
	sprintf(tagbuf,"%d",tag);	
	vasVaule = shmp->call_report.vas_record.smsNumber + shmp_peer->call_report.vas_record.smsNumber;
	sprintf(balancebuf,"%ld",vasVaule);
	totalLen = add_tlv(tagbuf,strlen(balancebuf), (u_char *)balancebuf,0x80,asnbuf);

	tag = 79;
	sprintf(tagbuf,"%d",tag);	
	gprsVal = shmp->call_report.vas_record.smsCharge + shmp_peer->call_report.vas_record.smsCharge;
	sprintf(balancebuf,"%lld",gprsVal);
	totalLen = add_tlv(tagbuf,strlen(balancebuf), (u_char *)balancebuf,0x80,asnbuf);

	tag = 80;
	sprintf(tagbuf,"%d",tag);
	vasVaule = shmp->call_report.vas_record.mmsSendNumber + shmp_peer->call_report.vas_record.mmsSendNumber;
	sprintf(balancebuf,"%ld",vasVaule);
	totalLen = add_tlv(tagbuf,strlen(balancebuf), (u_char *)balancebuf,0x80,asnbuf);
	
	tag = 81;
	sprintf(tagbuf,"%d",tag);
	gprsVal = shmp->call_report.vas_record.mmsSendCharge + shmp_peer->call_report.vas_record.mmsSendCharge;
	sprintf(balancebuf,"%lld",gprsVal);
	totalLen = add_tlv(tagbuf,strlen(balancebuf), (u_char *)balancebuf,0x80,asnbuf);

	tag = 82;
	sprintf(tagbuf,"%d",tag);
	vasVaule = shmp->call_report.vas_record.mmsRetrieveNumber + shmp_peer->call_report.vas_record.mmsRetrieveNumber;
	sprintf(balancebuf,"%ld",vasVaule);
	totalLen = add_tlv(tagbuf,strlen(balancebuf), (u_char *)balancebuf,0x80,asnbuf);
	
	tag = 83;
	sprintf(tagbuf,"%d",tag);
	gprsVal = shmp->call_report.vas_record.mmsRetrieveCharge + shmp_peer->call_report.vas_record.mmsRetrieveCharge;
	sprintf(balancebuf,"%lld",gprsVal);
	totalLen = add_tlv(tagbuf,strlen(balancebuf), (u_char *)balancebuf,0x80,asnbuf);

	tag = 84;
	sprintf(tagbuf,"%d",tag);
	vasVaule = shmp->call_report.vas_record.mmsEmailNumber + shmp_peer->call_report.vas_record.mmsEmailNumber;
	sprintf(balancebuf,"%ld",vasVaule);
	totalLen = add_tlv(tagbuf,strlen(balancebuf), (u_char *)balancebuf,0x80,asnbuf);
	
	tag = 85;
	sprintf(tagbuf,"%d",tag);
	gprsVal = shmp->call_report.vas_record.mmsEmailCharge + shmp_peer->call_report.vas_record.mmsEmailCharge;
	sprintf(balancebuf,"%lld",gprsVal);
	totalLen = add_tlv(tagbuf,strlen(balancebuf), (u_char *)balancebuf,0x80,asnbuf);
	/***********************		VAS daily report	**************************/
	
#ifdef _ZED_NO_CALLER_NUM_AND_EXPIRY_DATE_ // ussd_code daily report
	if (yx_ussd_daily_report == 0)
	{
		return totalLen;
	}
	int offset=86, tagPerCode=8, codeLen=0;
	for (i=0; i<USSDCODE_MAX_CODE_NUM; i++)
	{
		codeLen = strlen(shmp->ussdcode_report[i].code);
		if (codeLen <= 0)
		{
			//continue;
		}
		
		tag = offset + tagPerCode*i;
		sprintf(tagbuf,"%d",tag);
		totalLen = add_tlv(tagbuf, codeLen, (u_char *)shmp->ussdcode_report[i].code,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 1;
	    value = shmp->ussdcode_report[i].req_count;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 2;
	    value = shmp->ussdcode_report[i].req_duration;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 3;
	    value = shmp->ussdcode_report[i].err_timeout_count;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 4;
	    value = shmp->ussdcode_report[i].err_system_count;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 5;
	    value = shmp->ussdcode_report[i].err_msg_count;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 6;
	    value = 0;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
		
		tag = offset + tagPerCode*i + 7;
	    value = 0;
		sprintf(tagbuf,"%d",tag++);
		totalLen = AddInteger(tagbuf,value,0x80,asnbuf);
	}
#endif
	PutLogFunID("GetDailyReportByIndex2");

	//printfDailyLog(saveIndex);
	return totalLen;
}

int printfDailyLog(int index)
{
   _daily_report *shmp=NULL, *shmp_peer=NULL;
   
   int i;
   
   PutLogFunID("printfDailyLog");

   shmp = &pps_report.daily_report[index];
   shmp_peer = &pps_report.peer_daily_report[index];
   printf("------------------------------------------\n");
   printf("Time: %04d-%02d-%02d\n",
   shmp->year_month_day[0],
   shmp->year_month_day[1],
   shmp->year_month_day[2]);
   
   printf("account report\n");
   printf(" Fresh:       %05ld\n",shmp->account_report.user_num[0]);
   printf(" Normal:      %05ld\n",shmp->account_report.user_num[1]);
   printf(" Suspend:     %05ld\n",shmp->account_report.user_num[2]);
   printf(" Blacklisted: %05ld\n",shmp->account_report.user_num[3]);
   printf(" Released:    %05ld\n",shmp->account_report.user_num[4]);
   printf(" Total:       %05ld\n",shmp->account_report.total_num);
   printf(" Total balance:     %.0f\n",shmp->account_report.total_balance);
   printf(" Yesterday balance: %.0f\n",shmp->balance_summary.yesterday_balance);
   printf(" today recharge:    %.0f\n",shmp->balance_summary.today_recharge+
										shmp_peer->balance_summary.today_recharge);
   printf(" today charge:      %.0f\n",shmp->balance_summary.today_charge+
										shmp_peer->balance_summary.today_charge);

   printf("prepaid card report\n");
   for(i=0;i<MAX_VALUE_TYPE;i++){
     printf("Face value:   %03f\n",shmp->prepaid_card_report.face_value[i]);
     printf("used today:   %05ld\n",shmp->prepaid_card_report.used_today[i]);
     printf("total used:   %05ld\n",shmp->prepaid_card_report.total_used[i]);
     printf("unused:       %05ld\n",shmp->prepaid_card_report.unused[i]);
   }
    
   printf("call statistics\n");
   for(i=0;i<11;i++)
   {
      printf("call type:%s\n",call_type_name[i]);
	  printf("call times:    %03ld\n",shmp->call_report.call_record[i].call_times+shmp_peer->call_report.call_record[i].call_times);
	  printf("call duration: %03ld\n",shmp->call_report.call_record[i].call_duration+shmp_peer->call_report.call_record[i].call_duration);
	  printf("call charge:   %.0f\n",shmp->call_report.call_record[i].call_charge+shmp_peer->call_report.call_record[i].call_charge);
   }
   printf("------------------------------------------\n");
   return 1;
}

/* --- couple of functions --- */
void SaveDailyReport()
{
	char	fileName[]="../log/dailyreport.bak";
	FILE	*fpBak = NULL;
	int		index;

	fpBak = fopen(fileName,"w");
	if(fpBak == NULL) return;
	index = pps_report.ptrTail;

	fwrite(&pps_report.daily_report[index],sizeof(_daily_report),1,fpBak);
	fclose(fpBak);
	SendDailyReportToPeerServerForStop();
}

int LoadDailyReport()
{
	char	fileName[]="../log/dailyreport.bak";
	FILE	*fpBak = NULL;
	int		index;

	fpBak = fopen(fileName,"r");
	if(fpBak == NULL) return 0;
	index = pps_report.ptrTail;

	fread(&pps_report.daily_report[index],sizeof(_daily_report),1,fpBak);
	fclose(fpBak);
	if(pps_report.daily_report[index].year_month_day[0] !=time_now[0] ||
		pps_report.daily_report[index].year_month_day[1] !=time_now[1] ||
		pps_report.daily_report[index].year_month_day[2] !=time_now[2] )
	{
		memset(&pps_report.daily_report[index],0,sizeof(_daily_report));
		pps_report.daily_report[pps_report.ptrTail].year_month_day[0]=time_now[0];
		pps_report.daily_report[pps_report.ptrTail].year_month_day[1]=time_now[1];
		pps_report.daily_report[pps_report.ptrTail].year_month_day[2]=time_now[2];
	}


	return 1;
}

/* --- end of couple of functions --- */

/* --- couple of functions --- */
_prepaid_card_report  tmpCardReport;
int ClearCleanUsedCardForDailyReport(int index)
{
    int i, j;
    int flag[MAX_VALUE_TYPE];
    
    PutLogFunID("ClearCleanUsedCardForDailyReport");

    if(index<0 || index>=MAX_RECORDS_SAVED) 
    	return -1;

    memset(flag,0x00,sizeof(int)* MAX_VALUE_TYPE);
    memcpy(&tmpCardReport, 
    		&pps_report.daily_report[index].prepaid_card_report, 
    		sizeof(_prepaid_card_report));
    
    for(i=0;i<MAX_VALUE_TYPE;i++)
    {
        if(pps_report.daily_report[index].prepaid_card_report.face_value[i]<=0)
        	continue;
        
        for(j=0;j<MAX_VALUE_TYPE;j++)
        {
            if(tmpCardReport.face_value[i] == 
                pps_report.peer_daily_report[index].prepaid_card_report.face_value[j] )
            {
			tmpCardReport.used_today[i] +=
            	          pps_report.peer_daily_report[index].prepaid_card_report.used_today[j];
            	      flag[j] = 1;
            }  
        }        
    }
    
    for(i=0;i<MAX_VALUE_TYPE;i++)
    {
        if(flag[i] == 0)
        {
            for(j=0;j<MAX_VALUE_TYPE;j++)
            {
                if(tmpCardReport.face_value[j]<=0)
                {
                    tmpCardReport.face_value[j] =
            	          pps_report.peer_daily_report[index].prepaid_card_report.face_value[i];
                    
                    tmpCardReport.used_today[j] =
            	          pps_report.peer_daily_report[index].prepaid_card_report.used_today[i];
                }
            }
        }//flag=1,match
    }
    return 1;	
    
}

int GetPrecardSumData(int index, int type)
{
    int value=0;

    if(index<0 || index>=MAX_VALUE_TYPE) return 0;
    if(type<0 || type>=3) return 0;

    switch(type)
    {
        case 0:
            value = tmpCardReport.face_value[index];
        break;
        case 1:
            value = tmpCardReport.used_today[index];
        break;
        default:
            value = tmpCardReport.unused[index];		
        break;
    }
    return value;
}

int ReadDailyReportFromPeerServer()
{
	int				index;
    snmp_pdu        snmpbuf;
	snmp_addr		snmpaddr;
    var_list		*varlist;

	PutLogFunID("ReadDailyReportFromPeerServer");


	index = pps_report.ptrTail;

	snmpbuf.pdu_type = PDU_GET; //trap 
	snmpbuf.var_num	 = 0x01;

	snmpaddr.remote_ip = peer_server_ip;
    snmpaddr.remote_port = HEART_BEATING_PORT;
	snmpaddr.local_port  = HEART_BEATING_PORT;
	snmpaddr.broadcast   = 0x00;

    varlist = snmpbuf.var;
    varlist->oidlen   = 14;
	varlist->vartype  = 0x04;
	memcpy(&varlist->oid,PPS_OID_PREFIX,11*4);
	varlist->oid[11] = 0x01;
	varlist->oid[12] = 0x04;
    varlist->oid[13] = index;// 

    varlist->msglen  = 0;
    snmp_send(&snmpbuf,&snmpaddr);

	return 1;
}

int	ReadDailyReportRequest(u_char oidLen,DWORD *oid,u_char *pdata,BYTE *vartype)
{
	int index;

	PutLogFunID("ReadDailyReportRequest");
	if(oidLen<14) return -1;
	index = oid[13];
	if(index<0 || index>=MAX_RECORDS_SAVED) return -1;

	memcpy(pdata,
			&pps_report.daily_report[index],
			sizeof(_daily_report));
	return sizeof(_daily_report);
}

#if _ZED_NO_CALLER_NUM_AND_EXPIRY_DATE_ // ussd_code daily report
int	pps_update_ussd_code_state(char *code, int type, int result, int dur)
{
	_ussdcode_report *shmp = NULL;
	int index = pps_report.ptrTail % MAX_RECORDS_SAVED, i;
	switch (type)
	{
	case USSDCODE_TYPE_QUERY:
		shmp = &pps_report.daily_report[index].ussdcode_report[USSDCODE_TYPE_QUERY];
		break;
	case USSDCODE_TYPE_TOPUP:
		shmp = &pps_report.daily_report[index].ussdcode_report[USSDCODE_TYPE_TOPUP];
		break;
	case USSDCODE_TYPE_HOTLINE:
		shmp = &pps_report.daily_report[index].ussdcode_report[USSDCODE_TYPE_HOTLINE];
		break;
	case USSDCODE_TYPE_CHANNEL:
		for (i=USSDCODE_TYPE_CHANNEL; i<USSDCODE_MAX_CODE_NUM; i++)
		{
			if (pps_report.daily_report[index].ussdcode_report[i].code[0] == '\0')
			{
				strncpy(pps_report.daily_report[index].ussdcode_report[i].code, code, 3);
				shmp = &pps_report.daily_report[index].ussdcode_report[i];
				break;
			}
			else if (strncmp(pps_report.daily_report[index].ussdcode_report[i].code, code, 3) == 0)
			{
				shmp = &pps_report.daily_report[index].ussdcode_report[i];
				break;
			}
		}
		if (shmp == NULL)
		{
			return -1;// full?
		}
		break;
	default:
		return 0;
	}

	switch (result)
	{
	case USSDCODE_STAT_REQ:
		shmp->req_count++;
		break;
	case USSDCODE_STAT_DUR:
		shmp->req_duration += (dur / CYCLE_STATE_INTERVAL);
		break;
	case USSDCODE_STAT_ERR_TIMEOUT:
		if (dur > 0)
		{
			shmp->req_duration += (dur / CYCLE_STATE_INTERVAL);
		}
		shmp->err_timeout_count ++;
		break;
	case USSDCODE_STAT_ERR_SYSTEM:
		if (dur > 0)
		{
			shmp->req_duration += (dur / CYCLE_STATE_INTERVAL);
		}
		shmp->err_system_count ++;
		break;
	case USSDCODE_STAT_ERR_MSG:
		if (dur > 0)
		{
			shmp->req_duration += (dur / CYCLE_STATE_INTERVAL);
		}
		shmp->err_msg_count ++;
		break;
	default:
		return 0;
	}
	
	return 1;
}
#endif

int GetDailyReportResponse(snmp_pdu *pdu, snmp_addr *addr)
{

	int readDailyReportResponseIndex = pdu->var[0].oid[13];

	PutLogFunID("GetDailyReportResponse");

	getDailyReportResponseFlag = 1;

	if(readDailyReportResponseIndex>=MAX_RECORDS_SAVED) return 0;
	if(pdu->var[0].msglen != sizeof(_daily_report)) return 0;
	  
	memcpy(&pps_report.peer_daily_report[readDailyReportResponseIndex],
		  pdu->var[0].msg,
		  sizeof(_daily_report));

       if(UseExternalVC())
       {
          // ClearCleanUsedCardForDailyReport(readDailyReportResponseIndex);
       }
	//printfDailyLog(readDailyReportResponseIndex);
	return 1;
}
/* --- end of couple of functions --- */

/* --- couple of functions --- */
int SendDailyReportToPeerServerForStop()
{
	int				index;
    snmp_pdu        snmpbuf;
	snmp_addr		snmpaddr;
    var_list		*varlist;

	PutLogFunID("SendDailyReportToPeerServerForStop");

	index = pps_report.ptrTail;

	snmpbuf.pdu_type = 0x07; //trap 
	snmpbuf.var_num	 = 0x01;

	snmpaddr.remote_ip = peer_server_ip;
    snmpaddr.remote_port = HEART_BEATING_PORT;
	snmpaddr.local_port  = HEART_BEATING_PORT;
	snmpaddr.broadcast   = 0x00;

    varlist = snmpbuf.var;
    varlist->oidlen   = 13;
	varlist->vartype  = 0x04;
	memcpy(&varlist->oid,PPS_OID_PREFIX,11*4);
	varlist->oid[11] = 0x08;
	//varlist->oid[12] = 0x04;
    varlist->oid[12] = index;// 

    varlist->msglen  = sizeof(_daily_report);
    memcpy(varlist->msg, 
			(u_char *)&pps_report.daily_report[index], 
			sizeof(_daily_report));
    snmp_send(&snmpbuf,&snmpaddr);

	return 1;	
}

int GotSyncDailyReport(DWORD *oid,u_char *pdata,u_short dataLen)
{
	
	int index = oid[12];

	PutLogFunID("GotSyncDailyReport");


	if(index>=MAX_RECORDS_SAVED) return 0;
	if(dataLen != sizeof(_daily_report)) return 0;
	  
	memcpy(&pps_report.peer_daily_report[index],
		  pdata,
		  sizeof(_daily_report));

	//printfDailyLog(index);
	return 1;
}

/* --- end of couple functions --- */


void PPSSendUserSMSNotification(int head, int tail,char *msgSend)
/* head, tail is the account store index, msgSend is the notfication content */
{
	char	calledMSISDN[32]="";
	int	len,msglen=0;
	_prepaid_info	*shmp=NULL;
	
    	if (head >= MSISDN_HEAD_NUM || tail >= UNIT_STORE_ACCOUNT)
    		return;
    	msglen = strlen(msgSend);
	if(msglen<=0) 
		return;
	
	shmp = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];	
	len = shmp->msisdn[MAX_MSISDN_BLEN-1];
	BcdToAscii(calledMSISDN,shmp->msisdn,(MAX_MSISDN_BLEN-1)*2);
	calledMSISDN[len] = 0;

	
	smppSendMOSM(calledMSISDN,
		(char *)ppsParam.ppsTables.serviceNumber[InquiryNumberPosition].number, 
		(u_char *)msgSend,
		msglen,
		0);
}

extern int pps_crm_get_notify_days();
extern int pps_crm_get_status_vd();
extern void pps_send_update_subs_status_to_crm(_prepaid_info *user_ptr, int update_flag);
int AccountExpiredDateCheck_crm(_prepaid_info *user_ptr, int instance)
{
	int send_notify_days = pps_crm_get_notify_days();
	int status = user_ptr->status;
	int crm_update_user_status=0, crm_send_expired_notification=0;
	u_long	expired_secs =  user_ptr->mo_expiration_date;
	long		status_changed_seconds = (30*24*3600);

	if(user_ptr->crm_info.user_class == 0x02)//tourist
	{
		status_changed_seconds = (1*24*3600 );
	}
	else
	{
		int status_vd = pps_crm_get_status_vd();

		if(status_vd>0)
		{
			status_changed_seconds = (status_vd * 24 * 3600);
		}
	}

	switch(status)
	{
		case T_NORMAL:
			status_changed_seconds = 0;//status_changed_seconds;
		break;
		case T_SUSPEND:
			status_changed_seconds *= 1;
		break;
		case T_DISABLE:
			status_changed_seconds *= 2;
		break;
	}
	
	if((expired_secs + status_changed_seconds )< tvnow.tv_sec)
	{
		crm_update_user_status = 1;
	}
	
	if(status == T_NORMAL)
	{
		if( crm_update_user_status == 1)
		{
			user_ptr->status = T_SUSPEND;
		}
		else
		{
			if(send_notify_days>=1)
			{
				if ((expired_secs > ( (send_notify_days-1)*24*3600 +  tvnow.tv_sec)) && (expired_secs < ( send_notify_days*24*3600 +  tvnow.tv_sec)))
				{
					crm_send_expired_notification = 1;
				}
			}
		}
	}
	else if(status == T_SUSPEND)
	{
		if( crm_update_user_status == 1)
		{
			user_ptr->status = T_DISABLE;
		}
	}
	else if(status == T_DISABLE)
	{
		if( crm_update_user_status == 1)
		{
			user_ptr->status = T_RELEASED;
		}	
	}

//	if(crm_update_user_status )
//		user_ptr->mo_expiration_date = tvnow.tv_sec;

	if(!masterFlag) return 0;
	
	if(crm_update_user_status )
	{
		pps_send_update_subs_status_to_crm(user_ptr, 1);
	}
	else
	{
		if(crm_send_expired_notification)
		{
			pps_send_update_subs_status_to_crm(user_ptr, 2);
		}
	}

	if(user_ptr->status  == T_RELEASED)
	//if(status == T_DISABLE)	
	{			
			char msisdn[32];
			int len = user_ptr->msisdn[MAX_MSISDN_BLEN-1];
			BcdToAscii(msisdn, user_ptr->msisdn,(MAX_MSISDN_BLEN-1)*2);
			msisdn[len] = 0;

			DebugMsg(debugmib.display.asciiOut,"%s.%d try to delete RELEASED account: msisdn=%s, instance=%d",
                	__FUNCTION__, __LINE__, msisdn, instance);	

			SendAccountRealSync(instance,0.0,0.0,OMC_OCODE_DEL);
	}
	
	return 1;
}

int	AccountExpiredDateCheck()
{
	static		u_long LatchIndex=0;
	int			i, j, balance, cos_id, storeIndex;
	u_short		status=0, expiredFlag = 0;
	int 			len;
	char			caller_number[32];
	int			crm_update_user_status=0;
	COSTable			*cosTableItem;
	PutLogFunID("AccountExpiredDateCheck");

	
	
	if(time_now[3]<PERIODIC_CHARGE_HOUR || time_now[3]>(PERIODIC_CHARGE_HOUR+1)) {
		LatchIndex = 0;
		return 0;
	}
	
	i=LatchIndex/UNIT_STORE_ACCOUNT;
	j=LatchIndex%UNIT_STORE_ACCOUNT;
	storeIndex = LatchIndex;
	if(LatchIndex ++>=MSISDN_HEAD_NUM*UNIT_STORE_ACCOUNT)
	{
		return 0;//	LatchIndex = 0;
	}
	if(ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn[9]<MIN_MSISDN_ALEN)
		return 1;

	status = ramshm_ptr->prepaid_data.prepaid_info[i][j].status;
	if(status == T_FRESH) return 1;
	
	if(OCS_with_external_CRM())
		return	AccountExpiredDateCheck_crm(&ramshm_ptr->prepaid_data.prepaid_info[i][j], storeIndex);
		
	cos_id = ramshm_ptr->prepaid_data.prepaid_info[i][j].cos_id%MaxCosTableItem;
	cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];

	if(cosTableItem->accountValidity[0].actionWhenMOorMTExpired == 0) /* MO */
	{
		if((ramshm_ptr->prepaid_data.prepaid_info[i][j].mo_expiration_date+
			cosTableItem->accountValidity[0].daysKeepingAnExpiredAccount*24*3600)<tvnow.tv_sec)
			expiredFlag = 1;

	}
	else
	{
		if((ramshm_ptr->prepaid_data.prepaid_info[i][j].mt_expiration_date+
			cosTableItem->accountValidity[0].daysKeepingAnExpiredAccount*24*3600)<tvnow.tv_sec)
			expiredFlag = 1;
	}			
	if(expiredFlag)
	{
		ramshm_ptr->prepaid_data.prepaid_info[i][j].status = T_RELEASED;
		crm_update_user_status = 1;
		
		if(cosTableItem->accountValidity[0].actionAfterDaysKeepingAnExpiredAccount)
		{
			if(ramshm_ptr->prepaid_data.prepaid_info[i][j].balance>0)
			{
				balance = ramshm_ptr->prepaid_data.prepaid_info[i][j].balance;						
				ramshm_ptr->prepaid_data.prepaid_info[i][j].balance = 0;
				if(masterFlag)
				{
					SendOperatorRechargeCDR(i,j,-balance);
					if(cosTableItem->smsNotificationInquiry[0].smsNotificationWhenCleanBalance)
					{
						PPSSendUserSMSNotification(i, j, (char *)getSmsSentenceNative(0,SMS_CLEAR_FEE_NOTIFY));
					}
				}
			}
		}
	}			
	else if(ramshm_ptr->prepaid_data.prepaid_info[i][j].mt_expiration_date<tvnow.tv_sec)
	{
		if(status != T_BLACKLIST)
		{
			ramshm_ptr->prepaid_data.prepaid_info[i][j].status = T_SUSPEND;
			crm_update_user_status = 1;

		}
		if(cosTableItem->accountValidity[0].actionWhenAccountExpires)
		{
			if(ramshm_ptr->prepaid_data.prepaid_info[i][j].balance>0)
			{
				balance = ramshm_ptr->prepaid_data.prepaid_info[i][j].balance;						
				ramshm_ptr->prepaid_data.prepaid_info[i][j].balance = 0;
				if(masterFlag)
				{
					SendOperatorRechargeCDR(i,j,-balance);
					if(cosTableItem->smsNotificationInquiry[0].smsNotificationWhenCleanBalance)
					{
						PPSSendUserSMSNotification(i, j, (char *)getSmsSentenceNative(0,SMS_CLEAR_FEE_NOTIFY));
					}
				}
			}
		}
	}			
		
	if(ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_date<
			tvnow.tv_sec)
	{
		
		if(ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_balance >0)
		{
			balance = ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_balance;	
			ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_balance = 0;
			if(masterFlag)
				SendOperatorRechargeCDR(i,j,-balance);
		}
	}

	if(ramshm_ptr->prepaid_data.prepaid_info[i][j].bundle_info.validity_date > 10)
	{
		if(ramshm_ptr->prepaid_data.prepaid_info[i][j].bundle_info.validity_date < tvnow.tv_sec)
		{
			len = ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn[MAX_MSISDN_BLEN-1];
		
			BcdToAscii(caller_number, ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn, (MAX_MSISDN_BLEN-1)*2);
			caller_number[len ] = '\0';

			if (ramshm_ptr->prepaid_data.prepaid_info[i][j].bundle_info.data > 0)
			{
				subscribe_bundle_plan_send_used_up_info(caller_number, SMS_BUNDLE_PLAN_DATA_USEDUP);
			}
			
			memset(&ramshm_ptr->prepaid_data.prepaid_info[i][j].bundle_info, 0x00, sizeof(_bundle_info));
		}
	}
	
	if(crm_update_user_status )
	{
		if(OCS_with_external_CRM())
			pps_send_update_subs_status_to_crm(&ramshm_ptr->prepaid_data.prepaid_info[i][j], 1);
	}
	status = ramshm_ptr->prepaid_data.prepaid_info[i][j].status;	
	if(status != T_NORMAL) return 1;
	
	if(!IsPromotionTime(cosTableItem,tvnow))
	{
		ramshm_ptr->prepaid_data.prepaid_info[i][j].latch_flag &=0xFB;
	}


	return 1;
}

int	AccountLatchFlagCheck(int head, int tail)
{
	int			i,j ,len,cos_id;
	u_short		smPromptFlag=0;
	char		expire_date[128]="",promotion_expire_date[128]="",msisdn[128]="";
	COSTable			*cosTableItem;
	
	PutLogFunID("AccountLatchFlagCheck");
	
	i = head;
	j = tail;

	smPromptFlag = 0;

	if(ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn[9]<MIN_MSISDN_ALEN)
		return 0;

	
	cos_id = ramshm_ptr->prepaid_data.prepaid_info[i][j].cos_id%MaxCosTableItem;
	cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];
	
	if(ramshm_ptr->prepaid_data.prepaid_info[i][j].balance<
			cosTableItem->smsNotificationInquiry[0].insufficientBalanceThreshold)
	{
		if(cosTableItem->smsNotificationInquiry[0].smsNotificationWhenBalanceInsufficient)
		if(!(ramshm_ptr->prepaid_data.prepaid_info[i][j].latch_flag & 0x01))
		{
			ramshm_ptr->prepaid_data.prepaid_info[i][j].latch_flag |=0x01;
			smPromptFlag = 1;
		}
	}
	else
	{
		ramshm_ptr->prepaid_data.prepaid_info[i][j].latch_flag &=0xFE;
	}


	if(ramshm_ptr->prepaid_data.prepaid_info[i][j].mo_expiration_date<
			(cosTableItem->smsNotificationInquiry[0].theDaysSendingSMSBeforeExpiredDay)
				*24*3600+tvnow.tv_sec)
	{
		if(cosTableItem->smsNotificationInquiry[0].smsNotificationWhenExpired)
		if(!(ramshm_ptr->prepaid_data.prepaid_info[i][j].latch_flag & 0x02))
		{				
			ramshm_ptr->prepaid_data.prepaid_info[i][j].latch_flag |=0x02;
			smPromptFlag = 1;
		}
	}
	else
	{
		ramshm_ptr->prepaid_data.prepaid_info[i][j].latch_flag &=0xFD;
	}


	if(smPromptFlag )
	{
		len = ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn[9];
		if(len % 2==1) 
		{
			len ++;
			BcdToAscii(msisdn,
				ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn,
				len);
			msisdn[len-1] = 0;
		}
		else
		{
			BcdToAscii(msisdn,
				ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn,
				len);
			msisdn[len] = 0;
		}
		
		AsciiTime(expire_date,
				ramshm_ptr->prepaid_data.prepaid_info[i][j].mo_expiration_date);
		
		AsciiTime(promotion_expire_date,
				ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_date);
		
		smppSendAccountInfo(msisdn,
					ppsParam.ppsTables.serviceNumber[ScratchCardRechargeNumberPosition].number,
					(long)ramshm_ptr->prepaid_data.prepaid_info[i][j].balance,expire_date,
					(long)ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_balance,promotion_expire_date,
					0,"","", 
					(0x80 | ramshm_ptr->prepaid_data.prepaid_info[i][j].language_type ));
		return 1;
	}

	return 0;
}

int	CheckPromotionLatchFlag(_account_info *pInfo)
{
	int			i,j ,len,cos_id,loop;
	char		msisdn[32]="";
	char		promo_msg[256] = "", newsSMS[512] = "";
	char		*bufPtr[3],buf[3][32];
	//float		fValue=0;
	COSTable			*cosTableItem;
	
	PutLogFunID("CheckPromotionLatchFlag");

	i = pInfo->head;
	j=pInfo->tail;
	if(ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn[MAX_MSISDN_BLEN-1]<MIN_MSISDN_ALEN ||
		ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn[MAX_MSISDN_BLEN-1]>MAX_MSISDN_ALEN)
		return 1;
	
	cos_id = ramshm_ptr->prepaid_data.prepaid_info[i][j].cos_id%MaxCosTableItem;
	cosTableItem = &ppsParam.ppsTables.cosTable[cos_id];

       sprintf(promo_msg, "%s", (char *)getSmsSentenceNative(0,SMS_PROMOTION_NEWS));
       if(strlen(promo_msg)==0 || strcasecmp(promo_msg,"NULL")==0)
           return 1;
	
	if(IsPromotionTime(cosTableItem,tvnow))
	{
		if((ramshm_ptr->prepaid_data.prepaid_info[i][j].latch_flag & 0x04))
		{	
			return 0;
		}
		else
		{
			ramshm_ptr->prepaid_data.prepaid_info[i][j].latch_flag |=0x04;
		}
	}
	else 
		return 0;

	SendAccountRealSync(i*UNIT_STORE_ACCOUNT+j,0.0,0.0,OMC_OCODE_EDIT);
	len = ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn[MAX_MSISDN_BLEN-1];

	if(len % 2==1) 
	{
		len ++;
		BcdToAscii(msisdn,
				ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn,
				len);
		msisdn[len-1] = 0;
	}
	else
	{
		BcdToAscii(msisdn,
				ramshm_ptr->prepaid_data.prepaid_info[i][j].msisdn,
				len);
		msisdn[len] = 0;
	}

	bufPtr[0] = buf[0];
	bufPtr[1] = buf[1];
	bufPtr[2] = buf[2];

	for(loop=0;loop<MaxRechargeCardType;loop++)
	{
		if(cosTableItem->rechargePromotion[loop].rechargeCardCredit>0 && 
			cosTableItem->rechargePromotion[loop].promotionBonus>0)
		{
			sprintf(promo_msg, "%s", (char *)getSmsSentenceNative(0,SMS_PROMOTION_NEWS));
			/*
			fValue = (float)cosTableItem->rechargePromotion[loop].rechargeCardCredit;
			fillMoneyToContentWithoutCurrency(fValue,buf[0]);
			fValue = (float)cosTableItem->rechargePromotion[loop].promotionBonus;
			fillMoneyToContentWithoutCurrency(fValue,buf[1]);
			*/
			switch(ppsParam.ppsTables.promptResolution[0].currencyResolution)
			{
				  case 0:
				    sprintf(buf[0],"%d",cosTableItem->rechargePromotion[loop].rechargeCardCredit);
				    sprintf(buf[1],"%d",cosTableItem->rechargePromotion[loop].promotionBonus);
				  break;
				  case 1:
    				    sprintf(buf[0],"%.1f",cosTableItem->rechargePromotion[loop].rechargeCardCredit/10.0);
				    sprintf(buf[1],"%.1f",cosTableItem->rechargePromotion[loop].promotionBonus/10.0);
				  break;
				  case 2:
				  default:
				    sprintf(buf[0],"%.2f",cosTableItem->rechargePromotion[loop].rechargeCardCredit/100.0);
				    sprintf(buf[1],"%.2f",cosTableItem->rechargePromotion[loop].promotionBonus/100.0);				  	
				  break;
			}
			if(cosTableItem->rechargePromotion[loop].promotionValidity>0)
			{
				sprintf(buf[2],"%d",cosTableItem->rechargePromotion[loop].promotionValidity);
				sprintf(newsSMS,"%s",ppsParseSentence(promo_msg,3,bufPtr));
			}
			else
			{		
				sprintf(newsSMS,"%s",ppsParseSentence(promo_msg,2,bufPtr));
			}
			smppSendMOSM(msisdn,
				(char *)ppsParam.ppsTables.serviceNumber[ScratchCardRechargeNumberPosition].number,
				(u_char *)newsSMS,
				strlen(newsSMS),
				0);
		}		
	}
	

	return 1;
}

