Динамические программы
Динамические программы - это бонусные программы логика реализации которых основана на динамических Java классах. То есть, если вы хотите свой тип бонусной программы, то самым простым способом будет - это реализовать ее через динамические программы.
Для наглядности сейчас будет описан пример создания ДБП. Допустим нам нужна ДБП которая будет на каждый приход договора начислять бонусы, причем начисление зависит от некоторого коэффициента, который будет зависеть от кол-ва лет с момента создания договора, и начисление бонусов будем совершать только на первые два прихода сумма которых более 100р.
1) Создадим динамический класс и обязательно отнаследуем его от BonusProgramDynamicBase. Реализуем методы getTitle и accrualOfBonusImpl, первый соответственно возвращает название программы(оно будет отображаться в клиенте), а второй метод занимается начислением или/и расчетом некоторых значений(все зависет от ваших фантазий) для договоров. В нашем случае нам нужно реагировать на событие прихода платежа, потому мы еще переопределим метод onEvent.
Данный код можете использовать в качестве заготовки для вашего дин. кода( само собой изменив перед этим название класса и пакет ).
package
ru.bitel.bgbilling.bonus.myPrograms;
import
java.sql.Connection;
import
java.sql.SQLException;
import
ru.bitel.bgbilling.common.BGException;
import
ru.bitel.bgbilling.kernel.event.Event;
import
ru.bitel.bgbilling.plugins.bonus.common.bean.*;
import
ru.bitel.bgbilling.server.util.Setup;
import
ru.bitel.common.sql.ConnectionSet;
public
class
FirstProgram
extends
BonusProgramDynamicBase
{
@Override
public
String getTitle()
{
return
"Первая программа"
;
}
@Override
public
void
accrualOfBonusImpl( Connection con, BonusProgram program )
throws
SQLException, BGException
{
}
@Override
public
void
onEvent( Event event, Setup setup, ConnectionSet set )
throws
Exception
{
}
@Override
public
List<String> getWebBonusStrings(Connection con, BonusContractProgram program )
{
return
null
;
}
}
2) Далее заполним все методы, в результате у нас готовый дин. класс реализующий всю нашу логику. BonusProgramDynamicBase содержит основные методы для работы с бонусами, не забывайте ими пользоваться.
package
ru.bitel.bgbilling.bonus.myPrograms;
import
java.math.BigDecimal;
import
java.sql.Connection;
import
java.sql.SQLException;
import
java.util.ArrayList;
import
java.util.Calendar;
import
java.util.Date;
import
java.util.List;
import
ru.bitel.bgbilling.common.BGException;
import
ru.bitel.bgbilling.kernel.contract.api.common.bean.Contract;
import
ru.bitel.bgbilling.kernel.contract.api.server.bean.ContractDao;
import
ru.bitel.bgbilling.kernel.contract.balance.server.event.PaymentEvent;
import
ru.bitel.bgbilling.kernel.event.Event;
import
ru.bitel.bgbilling.kernel.module.common.bean.User;
import
ru.bitel.bgbilling.plugins.bonus.common.bean.BonusContractProgram;
import
ru.bitel.bgbilling.plugins.bonus.common.bean.BonusProgram;
import
ru.bitel.bgbilling.plugins.bonus.common.bean.BonusProgramDynamicBase;
import
ru.bitel.bgbilling.plugins.bonus.server.dao.BonusDao;
import
ru.bitel.bgbilling.server.util.Setup;
import
ru.bitel.common.Utils;
import
ru.bitel.common.sql.ConnectionSet;
import
bitel.billing.common.TimeUtils;
public
class
FirstProgram
extends
BonusProgramDynamicBase
{
@Override
public
String getTitle()
{
return
"Первая программа"
;
}
@Override
public
void
accrualOfBonusImpl( Connection con, BonusProgram program )
throws
SQLException, BGException
{
Calendar now = Calendar.getInstance();
// Производить расчеты будем только первого числа месяца. Это имеет смысл только если планировщик настроен на запуск каждый день.
if
( now.get( Calendar.DAY_OF_MONTH ) !=
1
)
return
;
ContractDao contractDao =
new
ContractDao( con, User.USER_SERVER );
for
(
int
contractId : bonusDao.getContractsOfThisProgram( program.getId(),
new
Date() ) )
//пробегаемся по всем договорам с этой программой
{
if
( !bonusDao.pluginInclude( contractId ) )
// перед этим убедимся, что плагин у договора все еще включен.
{
continue
;
}
map = bonusDao.getDataProgramOfContract( program.getId(), contractId );
// инициализируем мап данными обрабатываемого договора.
Contract contract = contractDao.get( contractId );
// получим кол-во лет с момента действия договора( это не точный способ, так как високосные года не будут учтены, но думаю для примера пойдет )
int
year = TimeUtils.hourDelta( TimeUtils.convertDateToCalendar( contract.getDateFrom() ), Calendar.getInstance() ) /
24
/
365
;
int
percent =
0
;
switch
( year )
// Тут мы выставляем процент. Более одного года = 5%, > 3 лет = 10%, > 5 лет = 15%
{
case
1
:
percent =
5
;
break
;
case
3
:
percent =
10
;
break
;
case
5
:
percent =
15
;
break
;
}
if
( percent >
0
)
{
// занесем посчитанный процент
map.put(
"percent"
, Integer.toString( percent ) );
}
map.put(
"count"
,
"0"
);
// обнулим месячный счетчик
updateProgramData( program.getId(), contractId, map );
// и сохраним изменения.
}
}
@Override
public
void
onEvent( Event event, Setup setup, ConnectionSet set )
throws
Exception
{
// настоятельно рекомендую вызывать метод у родителя, в нем производятся некоторые установки.
super
.onEvent( event, setup, set );
// Нас интересуют только события прихода платежа.
if
( event
instanceof
PaymentEvent && bonusDao.pluginInclude( event.getContractId() ) )
{
// получает все экземпляры программ
List<BonusContractProgram> list =
super
.getContractPrograms(
this
.getClass(),
new
Date() );
for
( BonusContractProgram contractProgram : list )
{
BonusProgram program = contractProgram.getProgram();
BigDecimal perc = Utils.parseBigDecimal( getParam(
"percent"
, program.getId() ), BigDecimal.ZERO );
int
count = Utils.parseInt( getParam(
"count"
, program.getId() ) );
if
( count <
3
&& perc.compareTo( BigDecimal.ZERO ) ==
1
)
// Проверим чтобы кол-во начислений было меньше 3 раз.
{
// Получили сумму бонусов. Предупреждаю! Данная сумма получена без учета вашего курса бонус->валюта.
BigDecimal sum = ((PaymentEvent)event).getPayment().getSum().multiply( perc.divide(
new
BigDecimal(
100
) ) );
updatePaymnent( sum, program );
// И совершаем начисление бонусов.
map.put(
"count"
, Integer.toString( count +
1
) );
updateProgramData( program.getId() );
// Увеличим счетчик кол-ва начислений и сохраним их.
}
}
}
}
@Override
public
List<String> getWebBonusStrings(Connection con, BonusContractProgram program )
{
ArrayList<String> list =
new
ArrayList<String>();
contractId = program.getContractId();
bonusDao =
new
BonusDao( con );
// Тут по желанию можно вывести данные, которое будут отображаться в ЛК.
return
list;
}
}
3) Далее необходимо прописать параметр dinamicBonusPrograms( если не был прописан до этого ) в конфигураторе плагина( Плагины->Настройки ), а в качестве значения прописать полные имена ваших дин. классов используемых для дин. программ, через запятую. В нашем случае еще понадобиться наш класс повесить на событие прихода платежа( Сервис->Автоматизация->Функции скриптов поведения ).
В нашем случае оно будет имет следующий вид: dinamicBonusPrograms=ru.bitel.bgbilling.bonus.myPrograms.FirstProgram. Допустим если вы написали там же еще вторую дин. программу с названием SecondProgram, то параметр будет иметь следующий вид:dinamicBonusPrograms=ru.bitel.bgbilling.bonus.myPrograms.FirstProgram,ru.bitel.bgbilling.bonus.myPrograms.SecondProgram
4) Далее стандартным способом создаете бонусную программу, просто вместо операционного типа выберите ваш тип. Далее, так же стандартным способом, добавляете вашу программу на договора.