Открытие абонплаты по первой установке соединения

Материал из BiTel WiKi

Перейти к: навигация, поиск

Версия биллинга - 5.1.

Скрипт открывает абонентскую плату на договоре по первой авторизации, если её не было и передаёт задание планировщику произвести начисление абонплат. Есть небольшой "костыль" - необходимо в BGRadiusDialup/lib либо скопировать либо сделать символическую ссылку на библиотеку BGBillingServer/lib/npay.jar. Т.к. скрипту нужны классы этой библиотеки.

Скрипт - обрабатывает событие RADIUS-аунтификация модуля DialUp.

import bitel.billing.server.util.*;
import bitel.billing.server.task.bean.*;
import java.sql.*;
import ru.bitel.bgbilling.kernel.network.radius.*;
import bitel.billing.server.npay.bean.*;
import bitel.billing.server.npay.*;
import java.util.*;
 
int NPAY_MID = 1;
int SERVICE = 1;
 
public void onEvent( event, setup, con, conSlave )
{
	int contractId = event.getContractId();
	RadiusPacket packet = event.getResponse();
 
	if( packet.getCode() == RadiusPacket.ACCESS_ACCEPT )
	{
		print( "It's accept packet" );
 
		String tableName = "npay_service_object_" + NPAY_MID;
		String query = "SELECT COUNT(*) FROM " + tableName + " WHERE cid=? AND sid=?";
 
		PreparedStatement ps = con.prepareStatement( query );		
		ps.setInt( 1, contractId );
		ps.setInt( 2, SERVICE );
 
		ResultSet rs = ps.executeQuery();
		if( !rs.next() || rs.getInt( 1 ) == 0 )
		{
			print( "Adding service" );
 
			ServiceObject serviceObject = new ServiceObject();
			serviceObject.setContractId( contractId );
			serviceObject.setServiceId( SERVICE );
			serviceObject.setDate1( new java.util.Date() );
 
			new ServiceObjectManager( con, NPAY_MID ).updateServiceObject( serviceObject );
			new RunTaskDataManager( con ).addTask( new Recalculator( NPAY_MID, new GregorianCalendar(), null, 0, String.valueOf( contractId ), "Автоматическое открытие абонплаты" ) );
		}
	}
}

Усложнённая версия скрипта. В дополнение снимает группу и устанавливает начало тарифного плана на дату первого входа. Это может быть необходимо при использовании в тарифах узла Диапазон наработки в режиме пропорциональном тарифу. Обратите внимание, что изменяется период также и закэшированного в памяти тарифа, который будет использоваться при тарификации первой сессии.

import bitel.billing.server.util.*;
import bitel.billing.server.task.bean.*;
import java.sql.*;
import ru.bitel.bgbilling.kernel.network.radius.*;
import bitel.billing.server.npay.bean.*;
import bitel.billing.server.npay.*;
import java.util.*;
import bitel.billing.server.contract.bean.*;
 
int NPAY_MID = 1;
int SERVICE = 1;
int GROUP_ID = 18;
 
public void onEvent( event, setup, con, conSlave )
{
	int contractId = event.getContractId();
	RadiusPacket packet = event.getResponse();
 
	if( packet.getCode() == RadiusPacket.ACCESS_ACCEPT )
	{
		print( "It's accept packet" );
 
		String tableName = "npay_service_object_" + NPAY_MID;
		String query = "SELECT COUNT(*) FROM " + tableName + " WHERE cid=? AND sid=?";
 
		PreparedStatement ps = con.prepareStatement( query );		
		ps.setInt( 1, contractId );
		ps.setInt( 2, SERVICE );
 
		ResultSet rs = ps.executeQuery();
		if( !rs.next() || rs.getInt( 1 ) == 0 )
		{
			print( "Adding service" );
 
			ServiceObject serviceObject = new ServiceObject();
			serviceObject.setContractId( contractId );
			serviceObject.setServiceId( SERVICE );
			serviceObject.setDate1( new java.util.Date() );
 
			new ServiceObjectManager( con, NPAY_MID ).updateServiceObject( serviceObject );
			new RunTaskDataManager( con ).addTask( new Recalculator( NPAY_MID, new GregorianCalendar(), null, 0, String.valueOf( contractId ), "Автоматическое открытие абонплаты" ) );
 
			ContractTariffManager ctm = new ContractTariffManager( con );
 
			// изменение периода тарифного плана
			List tariffList = ctm.getContractTariffList( contractId, (java.util.Date)null );
			for( ContractTariff tariff : tariffList )
			{
				tariff.setDate1( new GregorianCalendar() );
				ctm.updateContractTariff( tariff );
			}
 
			// удаление группы
			query = "UPDATE contract SET gr = gr&(~(1<<?)) WHERE id=?";
			ps = con.prepareStatement( query );
			ps.setInt( 1, GROUP_ID );
			ps.setInt( 2, contractId );
			ps.executeUpdate();
 
                        java.util.Date now = new java.util.Date();
 
			// изменение в кэше
			TariffTreeSet tts = event.getContract().getTts();
			for( TariffSetEntry tse : tts.getEntries() )
			{
				tse.setDateFrom( now );
			}
		}
	}
}

Усложнённая версия скрипта. При отсутствии абонплаты в договоре оценивает, достаточно ли в данный момент средств для списания абонплаты до конца текущего месяца без перевода договор в минус. Если средств недостаточно - Accept пакет подменяется на Reject. Если достаточно - открывается абонплата от текущего момента, период тарифа в базе и кэше радиуса меняется (для корректной работы узлов типа "Диапазон наработки").

import ru.bitel.common.*;
import bitel.billing.server.task.bean.*;
import java.sql.*;
import java.math.*;
import ru.bitel.bgbilling.kernel.network.radius.*;
import bitel.billing.server.npay.bean.*;
import bitel.billing.server.npay.*;
import java.util.*;
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.tariff.*;
import bitel.billing.server.tariff.TariffTreeSet.TariffSetEntry;
import ru.bitel.bgbilling.modules.npay.server.*;
 
int NPAY_MID = 1;
int SERVICE = 1;
 
int GROUP_ID = 18;
 
public void onEvent( event, setup, con, conSlave )
{
	int contractId = event.getContractId();
	RadiusPacket packet = event.getResponse();
 
	if( packet.getCode() == RadiusPacket.ACCESS_ACCEPT )
	{
		print( "It's accept packet" );
 
		ContractTariffManager ctm = new ContractTariffManager( con );
		ContractParameterManager cpm = new ContractParameterManager( con );		
		ServiceObjectManager som = new ServiceObjectManager( con, NPAY_MID );
		BalanceUtils bu = new BalanceUtils( con );
 
		Contract contract = event.getContract();
		java.util.Date curdate = new java.util.Date();
		Calendar now = new GregorianCalendar();
 
		String tableName = "npay_service_object_" + NPAY_MID;
		String query = "SELECT COUNT(*) FROM " + tableName + " WHERE cid=? AND sid=?";
 
		PreparedStatement ps = con.prepareStatement( query );		
		ps.setInt( 1, contractId );
		ps.setInt( 2, SERVICE );
 
		ResultSet rs = ps.executeQuery();
		if( !rs.next() || rs.getInt( 1 ) == 0 )
		{
			print( "Contract hasn't abon." );
 
			ServiceObject serviceObject = new ServiceObject();
			serviceObject.setContractId( contractId );
			serviceObject.setServiceId( SERVICE );
			serviceObject.setDate1( curdate );
 
			List serviceObjectList = new ArrayList();
			serviceObjectList.add( serviceObject );
 
			packet.setCode( RadiusPacket.ACCESS_REJECT );
 
			Calculator calculator = new Calculator();
			calculator.setExecutingTime( now );
			calculator.setPreCalc();
			calculator.setServiceObjectList( serviceObjectList );
			calculator.initTask( setup, 0, "mid=" + NPAY_MID );
			calculator.setCids( String.valueOf( contractId ) );
			calculator.startTask();
 
			if( !calculator.isCalcErrors() ) 
			{
				Map planAccountMap = calculator.getCostCache().getContractAccounts();
				BigDecimal planAccount = Utils.maskNull( (BigDecimal)planAccountMap.get( contractId ) );
 
          		print( "Plan account: " + planAccount );
 
				BigDecimal balance = bu.getBalance( curdate, contractId );
				if( balance.compareTo( planAccount ) < 0 )
				{
					print( "No enouth money for abon open!" );
				}
				else
				{
					// добавление абонплаты и запуск её начисления
					serviceObject = new ServiceObject();
					serviceObject.setContractId( contractId );
					serviceObject.setServiceId( SERVICE );
					serviceObject.setDate1( curdate );
 
					new ServiceObjectManager( con, NPAY_MID ).updateServiceObject( serviceObject );
					new RunTaskDataManager( con ).addTask( new Recalculator( NPAY_MID, new GregorianCalendar(), null, 0, String.valueOf( contractId ), "Автоматическое открытие абонплаты" ) );
 
					// изменение периода тарифного плана
					List tariffList = ctm.getContractTariffList( contractId, curdate );
					for( ContractTariff tariff : tariffList )
					{
						tariff.setDate1( now );
						ctm.updateContractTariff( tariff );
					}
 
					// удаление группы
					cpm.unsetGroup( contractId, GROUP_ID );
 
					// изменение в кэше
					TariffTreeSet tts = event.getContract().getTts();
					for( TariffSetEntry tse : tts.getEntries() )
					{
						tse.setDateFrom( curdate );
					}
 
					packet.setCode( RadiusPacket.ACCESS_ACCEPT );
				}
			}
			else
			{
				print( "Precalc errors!" );
			}
		}
	}
}
Личные инструменты