Организация семейства UNLIMIT тарифов на базе FreeBSD MPD

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

(Различия между версиями)
Перейти к: навигация, поиск
 
Строка 223: Строка 223:
</pre>
</pre>
-
Теперь пользователь должен перейти по ссылке в субдоговор и выбрать себе тариф. Далее он терпеливо жмет ссылку '''Смена тарифных планов''' до тех пор, пока тариф применится.
+
Теперь пользователь должен перейти по ссылке в субдоговор и поменять себе тариф, если нужно. По-умолчанию устанавливается тариф из шаблона.
{|
{|
|- valign=top
|- valign=top
-
| [[Изображение:Unlim_tariff_select.png|thumb|300px|Выбор тарифа]]
+
| [[Изображение:Unlim_tariff_select.png|thumb|300px|Смена тарифа]]  
-
| [[Изображение:Unlim_tariff_changed.png|thumb|300px|Тариф применен]]  
+
|}
|}
-
Чтобы тариф менялся быстро, устанавливаются следующие опции группы тарифов Свобода. Разрешено добавлять задание по смене тарифа на 10 дней вперед, само задание исполняется за 24 часа до момента начала действия тарифа.
+
Устанавливаются следующие опции группы тарифов Свобода. Разрешено добавлять задание по смене тарифа на 10 дней вперед, само задание исполняется за 24 часа до момента начала действия тарифа.
{|
{|
|- valign=top
|- valign=top
Строка 236: Строка 235:
|}
|}
-
В скрипте поведения субдоговоров FREEDOM должны быть обработчики запроса смены тарифа, смены тарифа и запроса учетного периода.
+
В скрипте поведения субдоговоров FREEDOM должны быть обработчики смены тарифа и запроса учетного периода.
{|
{|
|- valign=top
|- valign=top
Строка 242: Строка 241:
|}
|}
-
'''Добавление смены тарифа через Web''':
+
'''Список дат для смены тарифа''':
-
<pre>
+
<source lang="java">
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.tariff.bean.*;
import bitel.billing.server.tariff.bean.*;
Строка 250: Строка 249:
import java.util.*;
import java.util.*;
-
VPN_MID = 16;
+
VPN_MID = 3;
cid = event.getContractID();
cid = event.getContractID();
-
task = event.getTask();
+
dateList = new ArrayList();
-
fromDate = task.getFromDate();
+
event.setDateList( dateList );
-
 
+
-
tctm = new TariffChangeTaskManager( con );
+
-
 
+
-
print( "Set new tariff: " + task.getTariffPlanID() );
+
// проверка отсутсвия открытых учетных периодов в период действия тарифа
// проверка отсутсвия открытых учетных периодов в период действия тарифа
-
query = "SELECT COUNT(*) FROM calculate_period_" + VPN_MID + " WHERE cid=? AND start<=? AND ?<=end";
+
query = "SELECT end FROM calculate_period_" + VPN_MID + " WHERE cid=? AND start<=? AND ?<=end";
ps = con.prepareStatement( query );
ps = con.prepareStatement( query );
ps.setInt( 1, cid );
ps.setInt( 1, cid );
-
ps.setDate( 2, TimeUtils.convertCalendarToSqlDate( fromDate ) );
+
ps.setDate( 2, TimeUtils.convertDateToSqlDate( event.getDate() ) );
-
ps.setDate( 3, TimeUtils.convertCalendarToSqlDate( fromDate ) );
+
ps.setDate( 3, TimeUtils.convertDateToSqlDate( event.getDate() ) );
rs = ps.executeQuery();
rs = ps.executeQuery();
-
if( rs.first() && rs.getInt(1) > 0 )
+
// есть открытый период, можно менять тариф только после него
 +
if( rs.next() )
{
{
error( "Has an activated period.." );
error( "Has an activated period.." );
-
event.setMessage( "Вы не можете сменить тариф с даты, попадающей на действие открытого безлимитного периода!" );
+
 
-
return;
+
end = TimeUtils.convertDateToCalendar( rs.getDate( 1 ) );
 +
end.add( Calendar.DAY_OF_YEAR, 1 );
 +
 
 +
dateList.add( end.getTime() );
 +
}
 +
//  нет открытого периода в настоящий момент, можно менять с текущей даты
 +
else
 +
{
 +
dateList.add( new Date() );
}
}
 +
</source>
-
// удаляем добавленные сегодня задания на смену тарифных планов
+
'''Смена тарфиа по заданию пользователя''':
-
tctm.deleteTariffChangeTask( cid, fromDate );
+
<source lang="java">
-
</pre>
+
-
 
+
-
'''Обработка смены тарифа через Web''':
+
-
<pre>
+
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.tariff.bean.*;
import bitel.billing.server.tariff.bean.*;
Строка 289: Строка 290:
import java.util.*;
import java.util.*;
-
VPN_MID = 16;
+
VPN_MID = 3;
cid = event.getContractID();
cid = event.getContractID();
-
task = event.getTask();
+
event.setProcessed( true );
ctm =  new ContractTariffManager(  con );
ctm =  new ContractTariffManager(  con );
Строка 298: Строка 299:
csm = new ContractServiceManager( con );
csm = new ContractServiceManager( con );
-
print( "Set new tariff: " + task.getTariffPlanID() );
+
print( "Set new tariff: " + event.getToTariff().getID() );
-
// проверка отсутсвия открытых учетных периодов в момент начала действия тарифа
+
// текущий тарифный план
-
query = "SELECT COUNT(*) FROM calculate_period_" + VPN_MID + " WHERE cid=? AND start<=? AND ?<=end";
+
currentTariff = event.getFromTariff();
-
ps = con.prepareStatement( query );
+
if( currentTariff != null )
 +
{
 +
tpid = currentTariff.getTariffPlanID();
 +
if( (tpid > 69) || (tpid < 53) )
 +
{
 +
error("Wrong tariff: " + tpid );
 +
return;
 +
}
-
ps.setInt( 1, cid );
+
// проверка отсутсвия открытых учетных периодов в период действия тарифа
-
ps.setDate( 2, TimeUtils.convertCalendarToSqlDate( task.getFromDate() ) );
+
query = "SELECT COUNT(*) FROM calculate_period_" + VPN_MID + " WHERE cid=? AND start<=? AND ?<=end";
-
ps.setDate( 3, TimeUtils.convertCalendarToSqlDate( task.getFromDate() ) );
+
ps = con.prepareStatement( query );
-
rs = ps.executeQuery();
+
ps.setInt( 1, cid );
 +
ps.setDate( 2, TimeUtils.convertDateToSqlDate( event.getFromDate() ) );
 +
ps.setDate( 3, TimeUtils.convertDateToSqlDate( event.getFromDate() ) );
-
if( rs.first() && rs.getInt(1) > 0 ) {
+
rs = ps.executeQuery();
-
    error( "Has an activated period.." );
+
-
    return;
+
-
}
+
-
// день смены тарифного плана ("сегодняшний" день)
+
if( rs.next() && rs.getInt(1) > 0 )
-
fromDate = task.getFromDate();
+
{
-
print( "fromDate: " + TimeUtils.formatDate( fromDate ) );
+
error( "Has an activated period.." );
-
// день до смены тарифного плана ("вчерашний" день)
+
return;
-
endDate = new GregorianCalendar();
+
}
-
endDate.setTimeInMillis( fromDate.getTimeInMillis() - 24*3600*1000 );
+
-
print( "endDate: " + TimeUtils.formatDate( endDate ) );
+
-
// день после смены тарифного плана ("завтрашний" день)
+
-
tomorrowDate = new GregorianCalendar();
+
-
tomorrowDate.setTimeInMillis( fromDate.getTimeInMillis() + 24*3600*1000 );
+
-
print( "tomorrowDate: " + TimeUtils.formatDate( tomorrowDate ) );
+
-
// текущий тарифный план
+
// закрываем старый тариф днем ранее
-
currentTariff = ctm.getContractTariff( cid, fromDate );
+
endDate = new GregorianCalendar();
 +
endDate.setTime( event.getFromDate() );
-
if( currentTariff != null ) {
+
print( "endDate: " + TimeUtils.formatDate( endDate ) );
-
tpid = currentTariff.getTariffPlanID();
+
endDate.add( Calendar.DAY_OF_MONTH, -1 );
-
if( tpid>240 || tpid<237 ) {
+
-
error("Wrong current tariff: " + tpid );
+
-
return;
+
-
}
+
-
// закрываем текущий тариф "вчерашним" днем
 
currentTariff.setDate2( endDate );
currentTariff.setDate2( endDate );
-
ctm.updateContractTariff( String.valueOf( currentTariff.getID() ), currentTariff  );
 
-
print( "closed current tariff " + currentTariff.getTariffPlanID() + " from " + TimeUtils.formatDate( endDate ) );
 
-
}
 
-
// для "свободы" проверяем еще и отсутствие тарифного плана с "завтрашнего" дня
+
if( TimeUtils.dateBefore( currentTariff.getDate2(), currentTariff.getDate1() ) )
-
tomorrowTariff = ctm.getContractTariff( cid, tomorrowDate );
+
-
if( tomorrowTariff != null )
+
-
{
+
-
 
+
-
tpid = tomorrowTariff.getTariffPlanID();
+
-
if( tpid>240 || tpid<237 )
+
{
{
-
error("Wrong tomorrow tariff: " + tpid );
+
ctm.deleteContractTariff( currentTariff.getID() );
-
return;
+
}
 +
else
 +
{
 +
// ctm.updateContractTariff( String.valueOf( currentTariff.getID() ), currentTariff  );
 +
      ctm.updateContractTariff( currentTariff  );
}
}
-
 
-
// удаляем завтрашний тариф (для предотвращения всевозможных проблем)
 
-
ctm.deleteContractTariff( tomorrowTariff.getID() );
 
-
print( "deleted tomorrow tariff " + tomorrowTariff.getTariffPlanID() );
 
}
}
-
 
// вносим новый тариф
// вносим новый тариф
newPlan = new  ContractTariff();
newPlan = new  ContractTariff();
newPlan.setContractID( cid );
newPlan.setContractID( cid );
-
newPlan.setTariffPlanID( task.getTariffPlanID() );
+
newPlan.setTariffPlanID( event.getToTariff().getID() );
-
newPlan.setDate1( fromDate );
+
newPlan.setDate1( TimeUtils.convertDateToCalendar( event.getFromDate() ) );
newPlan.setComment( "Смена тарифа через WEB" );
newPlan.setComment( "Смена тарифа через WEB" );
-
ctm.updateContractTariff( "new", newPlan );
+
// ctm.updateContractTariff( "new", newPlan );
-
print( "opened new tariff " + task.getTariffPlanID() + " from " + TimeUtils.formatDate( fromDate ) );
+
ctm.updateContractTariff( newPlan );
-
</pre>
+
</source>
Скрипт '''Запрос учетного периода'''. В скрипте зашивается стоимость активации учетного периода UNLIM доступа для различных тарифов.
Скрипт '''Запрос учетного периода'''. В скрипте зашивается стоимость активации учетного периода UNLIM доступа для различных тарифов.
В данном скрипте логика немного усложнена учетом наличия параметра '''Льгота''' у договора.
В данном скрипте логика немного усложнена учетом наличия параметра '''Льгота''' у договора.
-
<pre>
+
<source lang="java">
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.util.*;
import bitel.billing.server.util.*;
import java.util.*;
import java.util.*;
 +
import java.math.*;
-
// код модуля VPN
+
VPN_MID = 3;
-
VPN_MID = 16;
+
CHARGE_TYPE = 21;
-
// тип расхода "Активация UNLIM"
+
-
CHARGE_TYPE = 56;
+
-
// код спискового параметра "Льгота"
+
-
LGOTA_PID = 391;
+
bu = new BalanceUtils( con ) ;
bu = new BalanceUtils( con ) ;
Строка 392: Строка 376:
chm = new ChargeManager( con );
chm = new ChargeManager( con );
ctm = new ContractTariffManager( con );
ctm = new ContractTariffManager( con );
-
 
-
cpu = new ContractParamUtils( con );
 
event.setProcessed( true );
event.setProcessed( true );
Строка 406: Строка 388:
if( contract == null ) {
if( contract == null ) {
-
     error( "Contract with ID " + event.getContractID() + " was not found!" );
+
     error( "Contract with ID " + cid + " was not found!" );
     return;
     return;
}
}
-
date = (GregorianCalendar)event.getRequestDate();
+
date_clndr = (Calendar)event.getRequestDate();
-
// Завтра
+
date = date_clndr.getTime();
-
dateTomorrow = date.clone();
+
-
dateTomorrow.add( Calendar.DAY_OF_YEAR, 1 );
+
-
currentTariff = ctm.getContractTariff( cid, date );
+
currentTariff = ctm.getContractTariff( cid, date_clndr );
if( currentTariff == null ) {
if( currentTariff == null ) {
   error( "Current tariff was not found!" );
   error( "Current tariff was not found!" );
   return;
   return;
-
}
 
-
else {
 
-
print( "currentTariff = " + currentTariff.getTariffPlanID() );
 
-
}
 
-
 
-
tomorrowTariff = ctm.getContractTariff( cid, dateTomorrow );
 
-
if( tomorrowTariff == null ) {
 
-
  error( "Tomorrow tariff was not found!" );
 
-
  return;
 
-
}
 
-
else {
 
-
print( "tomorrowTariff = " + tomorrowTariff.getTariffPlanID() );
 
}
}
PAY = 0;
PAY = 0;
-
// Получение спиского параметра "Льгота"
+
tpid = currentTariff.getTariffPlanID();
-
lgid = cpu.getListParam( cid, LGOTA_PID );
+
if( tpid == 53 ) {
-
 
+
    PAY = 290;
-
ctpid = currentTariff.getTariffPlanID();
+
}
-
 
+
else if ( tpid == 66 ) {
-
if( ctpid == 237 ) {
+
    PAY = 360;
-
PAY = 290;
+
}
}
-
else if ( ctpid == 238 ) {
+
else if ( tpid == 67 ) {
-
PAY = 660;
+
    PAY = 660;
}
}
-
else if ( ctpid == 239 ) {
+
else if ( tpid == 68 ) {
-
     PAY = 1360;
+
     PAY = 960;
}
}
-
else if ( ctpid == 240 ) {
+
else if ( tpid == 69 ) {
-
     PAY = 1960;
+
     PAY = 1660;
}
}
else {
else {
Строка 457: Строка 424:
}
}
-
// Скидка для льготников по всем тарифным планам
+
balance = bu.getBalance( date, cid );
-
// скидка 20%
+
-
if ( lgid == 933 )
+
-
{ PAY *= 0.8; }
+
-
// скидка 50%
+
-
else if ( lgid == 947 )  
+
-
{ PAY *= 0.5; }
+
-
ttpid = tomorrowTariff.getTariffPlanID();
+
if( balance.intValue() < PAY ) {
-
 
+
-
if( (ttpid < 237) && (ttpid > 240) ) {
+
-
    error( "Incorrect tomorrow tariff!" );
+
-
    return;
+
-
}
+
-
 
+
-
if( ctpid != ttpid ) {
+
-
    error( "Can't open a period today, because the tariff changes tomorrow!" );
+
-
    return;
+
-
}
+
-
 
+
-
balance = bu.getBalance( date, event.getContractID() );
+
-
//if( balance - contract.getLimit() < PAY ) {
+
-
if( balance < PAY ) {
+
     error( "Not enough money to open a period!!" );
     error( "Not enough money to open a period!!" );
     return;  
     return;  
Строка 486: Строка 433:
charge = new Charge();
charge = new Charge();
charge.setContractID( cid );
charge.setContractID( cid );
-
charge.setDate( date );
+
charge.setDate( date_clndr );
charge.setChargeTypeID( CHARGE_TYPE );
charge.setChargeTypeID( CHARGE_TYPE );
charge.setComment( "Активация периода UNLIM" );
charge.setComment( "Активация периода UNLIM" );
-
charge.setSumma( (float)PAY );
+
charge.setSumma( PAY );
chm.updateCharge( "new", charge );
chm.updateCharge( "new", charge );
Строка 496: Строка 443:
bu.updateBalance( date, cid );
bu.updateBalance( date, cid );
-
event.setPeriodStart( date );
+
date_start = new GregorianCalendar();
-
date = (Calendar)date.clone();
+
date_start.setTime( date );
-
 
+
date_end = (Calendar)date_start.clone();
-
date.add( Calendar.DAY_OF_YEAR, 30 );
+
date_end.add( Calendar.DAY_OF_YEAR, 30 );
-
event.setPeriodEnd( date );
+
event.setPeriodStart( date_start );
 +
event.setPeriodEnd( date_end );
print( "PAY = " + PAY );
print( "PAY = " + PAY );
-
</pre>
+
</source>
Теперь при входе по UNILIMIT логину, если у человека не активирован учетный период на настоящий момент - идет запрос в скрипт. Скрипт проверяет баланс и активирует период, если достаточно средств согласно тарифу. После этого по данному субдоговору можно осуществлять доступ 30 дней с момента активации. Далее при новом входе снова идет запрос в скрипт и так далее.
Теперь при входе по UNILIMIT логину, если у человека не активирован учетный период на настоящий момент - идет запрос в скрипт. Скрипт проверяет баланс и активирует период, если достаточно средств согласно тарифу. После этого по данному субдоговору можно осуществлять доступ 30 дней с момента активации. Далее при новом входе снова идет запрос в скрипт и так далее.
Пользователь может изменить свой UNLIM тариф. В скрипте смены тарифа производится проверка, что человек не изменят тариф в момент действия учетного периода.
Пользователь может изменить свой UNLIM тариф. В скрипте смены тарифа производится проверка, что человек не изменят тариф в момент действия учетного периода.
В противном случае возможна ситуация, что человек изменит тариф на более скоростной после активации периода и будет получает доступ быстрее оплаченного.
В противном случае возможна ситуация, что человек изменит тариф на более скоростной после активации периода и будет получает доступ быстрее оплаченного.

Текущая версия на 10:21, 22 декабря 2008

Ставится задача дополнительно к основному договору создать дополнительный сервис по активации UNLIMIT доступа на определенный период за фиксированную плату. При этом оплаченный UNLIMIT не должен блокироваться даже если основной сервис заблокирован.

Услуга называется Свобода, создаваемые субдоговора имеют префикс FREEDOM. Предлагается несколько тарифов в серии, различаются скоростью и ценой активации.

В скрипте поведения, который сопоставляется договорам физ. лиц добавляем обработчик события Получение списка доп. действий для Web-статистики и Получение списка доп. действий для договора.

Настройка функции, выводящей меню доп. действий

Задача скрипта - вывод дополнительных действий, доступных через Web-статистику и вкладку карточки договора Доп. действия. В данном случае список действий совпадает.

Код функции:

import bitel.billing.server.contract.bean.*;
 
cid = event.getContractID();
cm = new ContractManager( con );
 
contract = cm.getContractByID( cid );
 
if( contract == null )
{
	error( "Contract not found!" );
	return;
}
 
if( contract.getTitle().startsWith( "NK" ) )
{
	event.addAction( 1, "Активация UNLIM" );
}

Функция добавляет в список единственное событие с кодом 1.

Теперь зайдя на страницу статистики клиент видит следующую картину при переходе в меню Дополнительные действия.

Страница статистики пользователя

Вызов дополнительного действия передает в скрипт поведения событие Обработка доп. действия для договора, на которое также должна быть реализована функция-обработчик.

Скрипт создания FREEDOM субдоговора

Код скрипта приведен ниже.

import bitel.billing.server.contract.bean.*;
import bitel.billing.server.util.*;
import java.sql.*;
import java.util.*;
 
MAX_FREEDOM_COUNT = 1;
PATTERN_ID = 16;
MID = 3;
 
cm = new ContractManager( con );
 
contract = cm.getContractByID( event.getContractID() );
if( contract == null )
{
	error( "Contract not found!" );
	return;
}
 
if( event.getActionId() == 1 )
{
	if( contract.isSub() )
	{ 
		event.addReport( "Это субдоговор!"		);
		return;
	}
 
	subList = contract.getSubList();
	count = 0;
 
	print( "count=" + count );
 
	// есть субдоговора
	if( Utils.notBlankString( subList ) )
	{ 
		String query = "SELECT COUNT(*) FROM contract WHERE id IN ("	+ subList + " ) AND title LIKE 'FREEDOM%'";
		ResultSet rs = con.createStatement().executeQuery( query );
 
		if( rs.next() )
		{
			count = rs.getInt( 1 );
 
			if( count >= MAX_FREEDOM_COUNT )
			{
				event.addReport( "Больше активировать договора Свобода нельзя" );
				return;
			}
		}
	}
 
    mainLoginPswd = "";
    mainLogin = "";
 
	// выбор пароля основного логина
    query = "SELECT login, pswd FROM user_login_" + MID + 
			" WHERE (date1 IS NULL OR date1<=CURDATE()) AND (date2 IS NULL OR date2>=CURDATE()) AND cid=" + contract.getID();
	rs = con.createStatement().executeQuery( query );
	if( rs.next() )
	{
		mainLogin = rs.getString( 1 );
		mainLoginPswd = rs.getString( 2 );
	}
	else
	{
		event.addReport( "Не найдено активных логинов в основном договоре!" );
		print( "no active login" );
		return;
	}
 
 
	// создаем новый договор и добавляем его субдоговором
	subContract = cm.createFromPattern( PATTERN_ID, "FREEDOM_" + count + "/" + contract.getTitle(), new GregorianCalendar(), "" );
	cm.addSub( contract.getID(), subContract.getID() );
 
	while (true) {
		print("Trying to create a login.");
		// выбор номера логина
	    login = 0;
	    query = "SELECT * FROM user_login_" + MID + " ORDER BY login";
	    ps = con.prepareStatement( query );
 
    	rs = ps.executeQuery();
	    while ( rs.next() )
    	{
	        if ( login != rs.getInt( "login" ) )
    	    {
        	   break;
	        }
    	    else
    		{
	           login++;
    	    }
	    }
 
		// создание логина
	    query = "INSERT INTO user_login_" + MID + " ( cid, login, date1, status, session, pswd, realm_group ) VALUES ( ?, ?, ?, ?, ?, ?, ? )";
	    ps = con.prepareStatement( query );
	    ps.setInt( 1, subContract.getID() );
	    ps.setInt( 2, login );
	    ps.setDate( 3, TimeUtils.convertCalendarToSqlDate( subContract.getDate1() ) );
	    ps.setInt( 4, 0 );
	    ps.setInt( 5, 1 );
		ps.setString( 6, mainLoginPswd );
        ps.setString( 7, "freedom" );
		try {
	    	ps.executeUpdate();
			break;
		} catch (e) {
			print("Couldn't set login " + login + " due to an exception " + e);
		}
	}
 
	event.addReport( "Активирован безлимитный договор " + subContract.getTitle() + 
					", Вы можете найти ссылку на него в верхней области окна.\n" );
	event.addReport( "Ваш безлимитный логин " + login + ", пароль совпадает с паролем на логин " + mainLogin + "\n\n" );
	event.addReport( "Вам необходимо перейти в статистику договорa " + subContract.getTitle() + "(ссылка в левой верхней области экрана) и выбрать тариф в меню 'Смена тарифных планов'\n" );
	event.addReport( "Добавьте задание на смену с текущей или любой другой даты. Проконтролировать смену тарифа Вы можете, выбрав повторно пункт 'Смена тарифных планов'.\n\n" );
	event.addReport( "ВНИМАНИЕ! После активации тарифа Вы можете воспользоваться 'безлимитным' логином только в том случае, если на счету основного договора достаточно средств\n" );
 
 
	print( "UNLIM activated! Login=" + login + ", pswd=" + mainLoginPswd );
}

В скрипте приведена ссылка на код шаблона субдоговора. В шаблоне должны быть определены настройки:

  • лимита (очень низкий, чтобы не блокировало по низкому балансу)
  • любая из услуг VPN модуля (чтобы договор) соотносился с ним
  • прописан скрипт поведения, отдельный для FREEDOM договоров
  • прописана отдельная для FREEDOM договоров группа тарифов Свобода
  • тариф, устанавливаемый в договоре по умолчанию
Шаблон FREEDOM субдоговора
Шаблон FREEDOM субдоговора

Далее создаем линейку тарифных планов. Отличаются они только скоростью канала, поэтому все наследуются от базового тарифа.

Базовый тариф
Тариф со скоростью 64к

Все используемые наборы атрибутов предварительно должны быть прописаны в конфигурации модуля, примерно так:

#наборы атрибутов дя использования в тарифах
attrset.1.title=Канал 64
attrset.1.attributes=mpd-limit=out#1=all shape 60000 pass;mpd-limit=in#1=all rate-limit 10000000 pass
attrset.2.title=Канал 128
attrset.2.attributes=mpd-limit=out#1=all shape 128000 pass;mpd-limit=in#1=all rate-limit 10000000 pass
attrset.3.title=Канал 256
attrset.3.attributes=mpd-limit=out#1=all shape 256000 pass;mpd-limit=in#1=all rate-limit 10000000 pass
attrset.4.title=Канал 512
attrset.4.attributes=mpd-limit=out#1=all shape 512000 pass;mpd-limit=in#1=all rate-limit 10000000 pass

В тарифных планах должны быть опеределены цены всех услуг, привязанных к реалму default. Все цены ставятся нулевыми. На конструкцию диапазон 0 Гб за учетный период по цене 0 можно не обращать внимания, в данном контексте смысла она не имеет, цена может быть размещена прямо в узле Услуга.

Теперь пользователь выбирает дополнительное действие на сайте и получает сообщение:

Активация UNLIM
Активирован безлимитный договор FREEDOM_0/NK TEST1, Вы можете найти ссылку на него в верхней области окна.
Ваш безлимитный логин 121527, пароль совпадает с паролем на логин 121526

Вам необходимо перейти в статистику договорa FREEDOM_0/NK TEST1(ссылка в левой верхней области экрана) и выбрать тариф в меню 'Смена тарифных планов'
Добавьте задание на смену с текущей или любой другой даты. Проконтролировать смену тарифа Вы можете, выбрав повторно пункт 'Смена тарифных планов'.

ВНИМАНИЕ! После активации тарифа Вы можете воспользоваться 'безлимитным' логином только в том случае, если на счету основного договора достаточно средств

Теперь пользователь должен перейти по ссылке в субдоговор и поменять себе тариф, если нужно. По-умолчанию устанавливается тариф из шаблона.

Смена тарифа

Устанавливаются следующие опции группы тарифов Свобода. Разрешено добавлять задание по смене тарифа на 10 дней вперед, само задание исполняется за 24 часа до момента начала действия тарифа.

Группа тарифов Свобода

В скрипте поведения субдоговоров FREEDOM должны быть обработчики смены тарифа и запроса учетного периода.

Функции скрипта поведения Свобода

Список дат для смены тарифа:

import bitel.billing.server.contract.bean.*;
import bitel.billing.server.tariff.bean.*;
import bitel.billing.server.script.event.*;
import bitel.billing.server.util.*;
import java.util.*;
 
VPN_MID = 3;
 
cid = event.getContractID();
dateList = new ArrayList();
event.setDateList( dateList );
 
// проверка отсутсвия открытых учетных периодов в период действия тарифа
query = "SELECT end FROM calculate_period_" + VPN_MID + " WHERE cid=? AND start<=? AND ?<=end";
ps = con.prepareStatement( query );
 
ps.setInt( 1, cid );
ps.setDate( 2, TimeUtils.convertDateToSqlDate( event.getDate() ) );
ps.setDate( 3, TimeUtils.convertDateToSqlDate( event.getDate() ) );
 
rs = ps.executeQuery();
 
// есть открытый период, можно менять тариф только после него
if( rs.next() )
{
	error( "Has an activated period.." );
 
	end = TimeUtils.convertDateToCalendar( rs.getDate( 1 ) );
	end.add( Calendar.DAY_OF_YEAR, 1 );
 
	dateList.add( end.getTime() );
}
//  нет открытого периода в настоящий момент, можно менять с текущей даты
else
{
	dateList.add( new Date() );
}

Смена тарфиа по заданию пользователя:

import bitel.billing.server.contract.bean.*;
import bitel.billing.server.tariff.bean.*;
import bitel.billing.server.script.event.*;
import bitel.billing.server.util.*;
import java.util.*;
 
VPN_MID = 3;
 
cid = event.getContractID();
event.setProcessed( true );
 
ctm =  new ContractTariffManager(  con );
chm = new ChargeManager( con );
csm = new ContractServiceManager( con );
 
print( "Set new tariff: " + event.getToTariff().getID() );
 
// текущий тарифный план
currentTariff = event.getFromTariff();
if( currentTariff != null )
{
	tpid = currentTariff.getTariffPlanID();
	if( (tpid > 69) || (tpid < 53) )
	{
		 error("Wrong tariff: " + tpid );
		 return;
	}
 
	// проверка отсутсвия открытых учетных периодов в период действия тарифа
	query = "SELECT COUNT(*) FROM calculate_period_" + VPN_MID + " WHERE cid=? AND start<=? AND ?<=end";
	ps = con.prepareStatement( query );
 
	ps.setInt( 1, cid );
	ps.setDate( 2, TimeUtils.convertDateToSqlDate( event.getFromDate() ) );
	ps.setDate( 3, TimeUtils.convertDateToSqlDate( event.getFromDate() ) );
 
	rs = ps.executeQuery();
 
	if( rs.next() && rs.getInt(1) > 0 )
	{
		error( "Has an activated period.." );
		return;	
	}
 
	// закрываем старый тариф днем ранее
	endDate = new GregorianCalendar();
	endDate.setTime( event.getFromDate() );
 
	print( "endDate: " + TimeUtils.formatDate( endDate ) );
 
	endDate.add( Calendar.DAY_OF_MONTH, -1 );
 
	currentTariff.setDate2( endDate );
 
	if( TimeUtils.dateBefore( currentTariff.getDate2(), currentTariff.getDate1() ) )
	{
		ctm.deleteContractTariff( currentTariff.getID() );
	}
	else
	{
		// ctm.updateContractTariff( String.valueOf( currentTariff.getID() ), currentTariff  );
	      ctm.updateContractTariff( currentTariff  );
	}
}
 
// вносим новый тариф
newPlan = new  ContractTariff();
newPlan.setContractID( cid );
newPlan.setTariffPlanID( event.getToTariff().getID() );
newPlan.setDate1( TimeUtils.convertDateToCalendar( event.getFromDate() ) );
newPlan.setComment( "Смена тарифа через WEB" );
 
// ctm.updateContractTariff( "new", newPlan );
ctm.updateContractTariff( newPlan );

Скрипт Запрос учетного периода. В скрипте зашивается стоимость активации учетного периода UNLIM доступа для различных тарифов. В данном скрипте логика немного усложнена учетом наличия параметра Льгота у договора.

import bitel.billing.server.contract.bean.*;
import bitel.billing.server.util.*;
import java.util.*;
import java.math.*;
 
VPN_MID = 3;
CHARGE_TYPE = 21;
 
bu = new BalanceUtils( con ) ;
cm = new ContractManager( con );
chm = new ChargeManager( con );
ctm = new ContractTariffManager( con );
 
event.setProcessed( true );
 
if( event.getRequestDate() == null ) {
    error(  "event.requestDate() == null" );
    return;
}
 
cid = event.getContractID();
contract = cm.getContractByID( cid );
 
if( contract == null ) {
    error( "Contract with ID " + cid + " was not found!" );
    return;
}
 
date_clndr = (Calendar)event.getRequestDate();
date = date_clndr.getTime();
 
currentTariff = ctm.getContractTariff( cid, date_clndr );
if( currentTariff == null ) {
   error( "Current tariff was not found!" );
   return;
}
 
PAY = 0;
 
tpid = currentTariff.getTariffPlanID();
if(  tpid == 53 ) {
    PAY = 290;
}
else if ( tpid == 66 ) {
    PAY = 360;
}
else if ( tpid == 67 ) {
    PAY = 660;
}
else if ( tpid == 68 ) {
    PAY = 960;
}
else if ( tpid == 69 ) {
    PAY = 1660;
}
else {
    error( "Incorrect current tariff!" );
    return;
}
 
balance = bu.getBalance( date, cid );
 
if( balance.intValue() < PAY ) {
    error( "Not enough money to open a period!!" );
    return; 
}
 
charge = new Charge();
charge.setContractID( cid );
charge.setDate( date_clndr );
charge.setChargeTypeID( CHARGE_TYPE );
charge.setComment( "Активация периода UNLIM" );
charge.setSumma( PAY );
 
chm.updateCharge( "new", charge );
 
// обновляем баланс 
bu.updateBalance( date, cid );
 
date_start = new GregorianCalendar();
date_start.setTime( date );
date_end = (Calendar)date_start.clone();
date_end.add( Calendar.DAY_OF_YEAR, 30 );
event.setPeriodStart( date_start );
event.setPeriodEnd( date_end );
 
print( "PAY = " + PAY );

Теперь при входе по UNILIMIT логину, если у человека не активирован учетный период на настоящий момент - идет запрос в скрипт. Скрипт проверяет баланс и активирует период, если достаточно средств согласно тарифу. После этого по данному субдоговору можно осуществлять доступ 30 дней с момента активации. Далее при новом входе снова идет запрос в скрипт и так далее. Пользователь может изменить свой UNLIM тариф. В скрипте смены тарифа производится проверка, что человек не изменят тариф в момент действия учетного периода. В противном случае возможна ситуация, что человек изменит тариф на более скоростной после активации периода и будет получает доступ быстрее оплаченного.

Личные инструменты