Управление статусом договора по состоянию баланса
Материал из BiTel WiKi
Corban (Обсуждение | вклад) м |
Corwin (Обсуждение | вклад) |
||
(5 промежуточных версий не показаны.) | |||
Строка 10: | Строка 10: | ||
1. | 1. | ||
<source lang="java"> | <source lang="java"> | ||
+ | import bitel.billing.common.TimeUtils.*; | ||
import bitel.billing.server.contract.bean.*; | import bitel.billing.server.contract.bean.*; | ||
import bitel.billing.server.tariff.bean.*; | import bitel.billing.server.tariff.bean.*; | ||
Строка 16: | Строка 17: | ||
import bitel.billing.server.tariff.*; | import bitel.billing.server.tariff.*; | ||
import bitel.billing.server.util.*; | import bitel.billing.server.util.*; | ||
- | import bitel.billing.server.npay.*; | + | import bitel.billing.server.npay.bean.*; |
import bitel.billing.server.task.bean.RunTaskData; | import bitel.billing.server.task.bean.RunTaskData; | ||
import bitel.billing.server.task.bean.RunTaskDataManager; | import bitel.billing.server.task.bean.RunTaskDataManager; | ||
Строка 89: | Строка 90: | ||
msu = new ModuleAndServiceUtils( con ); | msu = new ModuleAndServiceUtils( con ); | ||
bu = new BalanceUtils( con ); | bu = new BalanceUtils( con ); | ||
+ | tu = new TimeUtils(); | ||
tpm = new TariffPlanManager(con); | tpm = new TariffPlanManager(con); | ||
Строка 94: | Строка 96: | ||
// получаем текущий баланс (с учетом данного платежа) | // получаем текущий баланс (с учетом данного платежа) | ||
- | balance = bu.getBalance(event.getGenerateTime(), cid); | + | balance = bu.getBalance(tu.convertCalendarToDate(event.getGenerateTime()), cid); |
- | limit = cn. | + | limit = cn.getBalanceLimit(); |
fbm = cn.getFakeBalanceMode(); | fbm = cn.getFakeBalanceMode(); | ||
bm = cn.getBalanceMode(); | bm = cn.getBalanceMode(); | ||
Строка 105: | Строка 107: | ||
totalCost = 0d; | totalCost = 0d; | ||
+ | /* | ||
+ | Для версии 4.5 | ||
+ | начало | ||
+ | */ | ||
// получаем список услуг | // получаем список услуг | ||
serviceList = csm.getContractServiceList( cid, df ); | serviceList = csm.getContractServiceList( cid, df ); | ||
Строка 116: | Строка 122: | ||
// Если услуга относится к модулю "NPay" | // Если услуга относится к модулю "NPay" | ||
if( mid == NPAY_MID ) { | if( mid == NPAY_MID ) { | ||
+ | |||
+ | /* | ||
+ | конец | ||
+ | */ | ||
+ | |||
+ | /* | ||
+ | То же, но для версии 4.6 | ||
+ | начало | ||
+ | */ | ||
+ | som = new ServiceObjectManager(con,NPAY_MID); | ||
+ | serviceList = som.getServiceObjectList( cid, -1 , -1, -1); | ||
+ | |||
+ | for( Iterator it = serviceList.iterator(); it.hasNext(); ) { | ||
+ | service = (ServiceObject)it.next(); | ||
+ | |||
+ | if ( TimeUtils.dateInRange( TimeUtils.convertCalendarToDate( egt ), service.getDate1(), service.getDate2() ) ) { | ||
+ | sid = service.getServiceId(); | ||
+ | |||
+ | /* | ||
+ | конец | ||
+ | */ | ||
+ | |||
// считаем сумму абонплаты | // считаем сумму абонплаты | ||
Строка 153: | Строка 181: | ||
if (StatusContract.getDate1().compareTo(df) < 0) { | if (StatusContract.getDate1().compareTo(df) < 0) { | ||
StatusContract.setDate2(dt); | StatusContract.setDate2(dt); | ||
- | cstm. | + | cstm.setContractStatus(StatusContract); |
} else { | } else { | ||
// или удаляем если дата начала больше даты окончания | // или удаляем если дата начала больше даты окончания | ||
Строка 163: | Строка 191: | ||
ncs.setDate1(df); | ncs.setDate1(df); | ||
ncs.setStatus(4); | ncs.setStatus(4); | ||
- | cstm.changeStatus(ncs); | + | cstm.changeStatus(ncs, 1, true); // 1 - код пользователя, от лица которого производится изменение состояния |
StatusContract = cstm.getStatus(cid, df); | StatusContract = cstm.getStatus(cid, df); | ||
// print("cm.getStatus("+df+"):"+StatusContract.getStatus() ); | // print("cm.getStatus("+df+"):"+StatusContract.getStatus() ); | ||
Строка 172: | Строка 200: | ||
2. | 2. | ||
<source lang="java"> | <source lang="java"> | ||
+ | import bitel.billing.common.TimeUtils.*; | ||
import bitel.billing.server.contract.bean.*; | import bitel.billing.server.contract.bean.*; | ||
import bitel.billing.server.tariff.bean.*; | import bitel.billing.server.tariff.bean.*; | ||
Строка 179: | Строка 208: | ||
import bitel.billing.server.util.*; | import bitel.billing.server.util.*; | ||
import bitel.billing.server.npay.*; | import bitel.billing.server.npay.*; | ||
+ | import bitel.billing.server.npay.bean.*; | ||
import bitel.billing.server.task.bean.RunTaskData; | import bitel.billing.server.task.bean.RunTaskData; | ||
import bitel.billing.server.task.bean.RunTaskDataManager; | import bitel.billing.server.task.bean.RunTaskDataManager; | ||
Строка 226: | Строка 256: | ||
tts = cman.getRealtimeTariffTreeSet( cid, df, "npay", NPAY_MID, true ); | tts = cman.getRealtimeTariffTreeSet( cid, df, "npay", NPAY_MID, true ); | ||
msu = new ModuleAndServiceUtils( con ); | msu = new ModuleAndServiceUtils( con ); | ||
+ | tu = new TimeUtils(); | ||
bu = new BalanceUtils( con ); | bu = new BalanceUtils( con ); | ||
// получаем текущий баланс (с учетом данного платежа) | // получаем текущий баланс (с учетом данного платежа) | ||
- | balance = bu.getBalance(event.getGenerateTime(), cid); | + | balance = bu.getBalance(tu.convertCalendarToDate(event.getGenerateTime()), cid); |
- | limit = cn. | + | limit = cn.getBalanceLimit(); |
fbm = cn.getFakeBalanceMode(); | fbm = cn.getFakeBalanceMode(); | ||
bm = cn.getBalanceMode(); | bm = cn.getBalanceMode(); | ||
Строка 242: | Строка 273: | ||
totalCost = 0d; | totalCost = 0d; | ||
- | + | /* | |
+ | Для версии 4.5 | ||
+ | начало | ||
+ | */ | ||
// получаем список услуг | // получаем список услуг | ||
serviceList = csm.getContractServiceList( cid, df ); | serviceList = csm.getContractServiceList( cid, df ); | ||
Строка 254: | Строка 288: | ||
// Если услуга относится к модулю "NPay" | // Если услуга относится к модулю "NPay" | ||
if( mid == NPAY_MID ) { | if( mid == NPAY_MID ) { | ||
+ | |||
+ | /* | ||
+ | конец | ||
+ | */ | ||
+ | |||
+ | /* | ||
+ | То же, но для версии 4.6 | ||
+ | начало | ||
+ | */ | ||
+ | som = new ServiceObjectManager(con,NPAY_MID); | ||
+ | serviceList = som.getServiceObjectList( cid, -1 , -1, -1); | ||
+ | |||
+ | for( Iterator it = serviceList.iterator(); it.hasNext(); ) { | ||
+ | service = (ServiceObject)it.next(); | ||
+ | |||
+ | if ( TimeUtils.dateInRange( TimeUtils.convertCalendarToDate( egt ), service.getDate1(), service.getDate2() ) ) { | ||
+ | sid = service.getServiceId(); | ||
+ | |||
+ | /* | ||
+ | конец | ||
+ | */ | ||
+ | |||
+ | |||
// считаем сумму абонплаты | // считаем сумму абонплаты | ||
Строка 291: | Строка 348: | ||
if (StatusContract.getDate1().compareTo(df) < 0) { | if (StatusContract.getDate1().compareTo(df) < 0) { | ||
StatusContract.setDate2(dt); | StatusContract.setDate2(dt); | ||
- | cm. | + | cm.setContractStatus(StatusContract); |
} else { | } else { | ||
// или удаляем если дата начала больше даты окончания | // или удаляем если дата начала больше даты окончания | ||
Строка 301: | Строка 358: | ||
ncs.setDate1(df); | ncs.setDate1(df); | ||
ncs.setStatus(0); | ncs.setStatus(0); | ||
- | cm.changeStatus(ncs); | + | cm.changeStatus(ncs, 1, true); |
StatusContract = cm.getStatus(cid, df); | StatusContract = cm.getStatus(cid, df); | ||
Строка 307: | Строка 364: | ||
// запускаем пересчет абонплат для договора cid | // запускаем пересчет абонплат для договора cid | ||
- | + | new RunTaskDataManager(con).addTask(new Recalculator(NPAY_MID, db, "", 0, ""+cid)); | |
- | + | ||
- | + | ||
} | } | ||
} | } | ||
</source> | </source> | ||
+ | |||
+ | Обратите внимание на изменения по работе с услугами модуля NPAY в версии 4.6 | ||
Если есть вопросы по скриптам, пишите в [http://www.bgbilling.ru/forum/privmsg.php?mode=post&u=1576 личку] | Если есть вопросы по скриптам, пишите в [http://www.bgbilling.ru/forum/privmsg.php?mode=post&u=1576 личку] |
Текущая версия на 17:02, 23 октября 2009
Предлагаю вариант управления начислением абонплаты в зависимости от баланса.
Всего используется два скрипта:
1. При наступлении события по таймеру (например, каждое первое число в 00:00) необходимо определить сумму необходимую для списания абонплаты и сравнить ее с балансом договора. Если средств недостаточно, то изменить статус договора на "Приостановлен" (в этом состоянии абонплата не начисляется)
2. При наступлении события "Поступление платежа", если договор в состоянии "Приостановлен", то проверяется также как и в первом случае достаточность средств. Если денег хватает, то статус изменяется на "Активен" и производится начисление абонплат.
1.
import bitel.billing.common.TimeUtils.*; import bitel.billing.server.contract.bean.*; import bitel.billing.server.tariff.bean.*; import bitel.billing.server.script.event.*; import bitel.billing.server.service.bean.*; import bitel.billing.server.tariff.*; import bitel.billing.server.util.*; import bitel.billing.server.npay.bean.*; import bitel.billing.server.task.bean.RunTaskData; import bitel.billing.server.task.bean.RunTaskDataManager; import java.util.*; // Если это таймер на начало месяца, в п.1, иначе выход // соответственно не забываем добавить параметр запуска в задачу "flag=1" // (вместо 1 подставляем любое число, но оно же должно быть в следующем условии =) if (event.getFlag() != 1 ) { return; } // номер модуля NPAY NPAY_MID = 4; cid = event.getContractID(); cstm = new ContractStatusManager( con ); // округляем день (на 00:00:00) события egt = event.getGenerateTime(); df = egt.clone(); df.clear(); df.set(egt.get(Calendar.YEAR), egt.get(Calendar.MONTH), egt.get(Calendar.DAY_OF_MONTH)); // получаем день, предыдущий событию dt = df.clone(); dt.roll(Calendar.DAY_OF_YEAR, -1); db = df.clone(); db.roll(Calendar.MONTH, -2); //print( df ); //print( dt ); //print( db ); // определяем текущий статус договора StatusContractList = cstm.getStatusList(cid, event.getGenerateTime()); if (StatusContractList.size() == 0) return; StatusContract = StatusContractList.get(0); print("StatusContract.getStatus():"+StatusContract.getStatus() ); contract = new ContractManager(con).getContractByID(cid); contract_groups = contract.getGroups(); // выбираем только нужную группу договоров (нам нужна только 1 группа) if ((contract_groups & (1L)) > 0) { internet = 1; } else { internet = 0; } if( StatusContract.getStatus() == 0 && internet == 1) { // 1. определить нужно ли приостанавливать договор (если есть абонплата и баланс меньше лимита) // 1.1 определить баланс и лимит: если баланс > лимита - выход, если меньше, то см. п.1.2 ctm = new ContractTariffManager( con ); csm = new ContractServiceManager( con ); cu = new ContractUtils( con ); cm = new ContractManager( con ); cn = cm.getContractByID( cid ); tts = cm.getRealtimeTariffTreeSet( cid, df, "npay", NPAY_MID, true ); msu = new ModuleAndServiceUtils( con ); bu = new BalanceUtils( con ); tu = new TimeUtils(); tpm = new TariffPlanManager(con); // получаем текущий баланс (с учетом данного платежа) balance = bu.getBalance(tu.convertCalendarToDate(event.getGenerateTime()), cid); limit = cn.getBalanceLimit(); fbm = cn.getFakeBalanceMode(); bm = cn.getBalanceMode(); print ( "balance = "+balance ); print ( "limit = "+limit ); print ( "fbm = "+fbm+"; bm = "+bm ); // 1.2 получить наработку для всех услуг типа "Абонплата" и если она больше 0, то в п.2 иначе выход totalCost = 0d; /* Для версии 4.5 начало */ // получаем список услуг serviceList = csm.getContractServiceList( cid, df ); for( Iterator it = serviceList.iterator(); it.hasNext(); ) { service = (ContractService)it.next(); sid = service.getServiceID(); mid = msu.getService(sid).getModuleId(); // print ( "Service.title "+msu.getService(sid).getTitle() ); // print ( "Module.title "+msu.getModule(mid).getTitle() ); // Если услуга относится к модулю "NPay" if( mid == NPAY_MID ) { /* конец */ /* То же, но для версии 4.6 начало */ som = new ServiceObjectManager(con,NPAY_MID); serviceList = som.getServiceObjectList( cid, -1 , -1, -1); for( Iterator it = serviceList.iterator(); it.hasNext(); ) { service = (ServiceObject)it.next(); if ( TimeUtils.dateInRange( TimeUtils.convertCalendarToDate( egt ), service.getDate1(), service.getDate2() ) ) { sid = service.getServiceId(); /* конец */ // считаем сумму абонплаты // перебор тарифов в порядке позиций сначала персональных, потом глобальных for( TariffModuleTree tree : tts.getTreeList( df ) ) { req = new TariffRequest(); req.setRequestParam( "action", "calculate" ); req.setRequestParam( "sid", sid ); // считаем абонплату пропорционально количеству дней до конца месяца(действует для тарифов "Пропорционально периоду") // всего дней в месяце req.setRequestParam( "month_days", df.getActualMaximum(Calendar.DAY_OF_MONTH) ); // всего дней до конца месяца req.setRequestParam( "period_days", df.getActualMaximum(Calendar.DAY_OF_MONTH) - df.get(Calendar.DAY_OF_MONTH) + 1 ); tree.processRequest( req ); cost = (Double) req.getResponseParam( "cost" ); // print ( "cost:" + cost ); if( req.wasAccepted() && cost != null ) { print( cost ); totalCost += cost; break; } } } } print ("totalCost = "+totalCost); if ( totalCost <= 0 || balance-totalCost >= limit) { print ( "Все ОК!" ); return; } // 2. Приостановить договор. установить статус "Приостановлен" if (StatusContract.getDate1().compareTo(df) < 0) { StatusContract.setDate2(dt); cstm.setContractStatus(StatusContract); } else { // или удаляем если дата начала больше даты окончания cstm.deleteStatus(StatusContract.getId()); } //создаем новое сосотояние ncs = new ContractStatus(); ncs.setContractId(cid); ncs.setDate1(df); ncs.setStatus(4); cstm.changeStatus(ncs, 1, true); // 1 - код пользователя, от лица которого производится изменение состояния StatusContract = cstm.getStatus(cid, df); // print("cm.getStatus("+df+"):"+StatusContract.getStatus() ); }
Пересчет абонплаты производится с помощью стандартной задачи для всех договоров. Только учтите, что задача "расчет абонплаты" должен запускаться после таймера с вышеуказанным скриптом с учетом времени его выполнения.
2.
import bitel.billing.common.TimeUtils.*; import bitel.billing.server.contract.bean.*; import bitel.billing.server.tariff.bean.*; import bitel.billing.server.script.event.*; import bitel.billing.server.service.bean.*; import bitel.billing.server.tariff.*; import bitel.billing.server.util.*; import bitel.billing.server.npay.*; import bitel.billing.server.npay.bean.*; import bitel.billing.server.task.bean.RunTaskData; import bitel.billing.server.task.bean.RunTaskDataManager; import java.util.*; NPAY_MID = 4; cid = event.getContractID(); cm = new ContractStatusManager( con ); // округляем день (на 00:00:00) платежа egt = event.getGenerateTime(); df = egt.clone(); df.clear(); df.set(egt.get(Calendar.YEAR), egt.get(Calendar.MONTH), egt.get(Calendar.DAY_OF_MONTH)); // получаем день, предыдущий платежу dt = df.clone(); dt.roll(Calendar.DAY_OF_YEAR, -1); // получаем дату начала месяца db = df.clone(); db.set(Calendar.DAY_OF_MONTH, 1); // определяем текущий статус договора StatusContractList = cm.getStatusList(cid, event.getGenerateTime()); if (StatusContractList.size() == 0) return; StatusContract = StatusContractList.get(0); print("StatusContract.getStatus():"+StatusContract.getStatus() ); // если договор приостановлен, то определяем размер абонплаты для снятия и сравниваем с балансом после платежа if( StatusContract.getStatus() == 4 ) { ctm = new ContractTariffManager( con ); csm = new ContractServiceManager( con ); cu = new ContractUtils( con ); cman = new ContractManager( con ); cn = cman.getContractByID( cid ); tts = cman.getRealtimeTariffTreeSet( cid, df, "npay", NPAY_MID, true ); msu = new ModuleAndServiceUtils( con ); tu = new TimeUtils(); bu = new BalanceUtils( con ); // получаем текущий баланс (с учетом данного платежа) balance = bu.getBalance(tu.convertCalendarToDate(event.getGenerateTime()), cid); limit = cn.getBalanceLimit(); fbm = cn.getFakeBalanceMode(); bm = cn.getBalanceMode(); print ( "balance = "+balance ); print ( "limit = "+limit ); print ( "fbm = "+fbm+"; bm = "+bm ); totalCost = 0d; /* Для версии 4.5 начало */ // получаем список услуг serviceList = csm.getContractServiceList( cid, df ); for( Iterator it = serviceList.iterator(); it.hasNext(); ) { service = (ContractService)it.next(); sid = service.getServiceID(); mid = msu.getService(sid).getModuleId(); // print ( "Service.title "+msu.getService(sid).getTitle() ); // print ( "Module.title "+msu.getModule(mid).getTitle() ); // Если услуга относится к модулю "NPay" if( mid == NPAY_MID ) { /* конец */ /* То же, но для версии 4.6 начало */ som = new ServiceObjectManager(con,NPAY_MID); serviceList = som.getServiceObjectList( cid, -1 , -1, -1); for( Iterator it = serviceList.iterator(); it.hasNext(); ) { service = (ServiceObject)it.next(); if ( TimeUtils.dateInRange( TimeUtils.convertCalendarToDate( egt ), service.getDate1(), service.getDate2() ) ) { sid = service.getServiceId(); /* конец */ // считаем сумму абонплаты // перебор тарифов в порядке позиций сначала персональных, потом глобальных for( TariffModuleTree tree : tts.getTreeList( df ) ) { req = new TariffRequest(); req.setRequestParam( "action", "calculate" ); req.setRequestParam( "sid", sid ); // считаем абонплату пропорционально количеству дней до конца месяца(действует для тарифов "Пропорционально периоду") // всего дней в месяце req.setRequestParam( "month_days", df.getActualMaximum(Calendar.DAY_OF_MONTH) ); // всего дней до конца месяца req.setRequestParam( "period_days", df.getActualMaximum(Calendar.DAY_OF_MONTH) - df.get(Calendar.DAY_OF_MONTH) + 1 ); tree.processRequest( req ); cost = (Double) req.getResponseParam( "cost" ); print ( "cost:" + cost ); if( req.wasAccepted() && cost != null ) { print( cost ); totalCost += cost; break; } } } } print (totalCost+" : "+balance+" - "+limit); // если денег на продление услуг хватает, то меняем статус договора и даем задание на обсчет услуг с абонплатой if (totalCost > 0 && totalCost < (balance - limit)) { //обновляем дату окончания предыдущего состояния if (StatusContract.getDate1().compareTo(df) < 0) { StatusContract.setDate2(dt); cm.setContractStatus(StatusContract); } else { // или удаляем если дата начала больше даты окончания cm.deleteStatus(StatusContract.getId()); } //создаем новое сосотояние ncs = new ContractStatus(); ncs.setContractId(cid); ncs.setDate1(df); ncs.setStatus(0); cm.changeStatus(ncs, 1, true); StatusContract = cm.getStatus(cid, df); print("cm.getStatus("+df+"):"+StatusContract.getStatus() ); // запускаем пересчет абонплат для договора cid new RunTaskDataManager(con).addTask(new Recalculator(NPAY_MID, db, "", 0, ""+cid)); } }
Обратите внимание на изменения по работе с услугами модуля NPAY в версии 4.6
Если есть вопросы по скриптам, пишите в личку