Снятие абонентской платы в дебитовых договорах
Материал из BiTel WiKi
Lda (Обсуждение | вклад) |
AlexandrV (Обсуждение | вклад) м |
||
(2 промежуточные версии не показаны) | |||
Строка 407: | Строка 407: | ||
}; | }; | ||
</source> | </source> | ||
+ | |||
+ | |||
+ | |||
+ | В новой версии билинга (4.6) эти скрипты не работают. Пришлось немного изменить, чтобы заработали. В яве не | ||
+ | спец, поэтому пошел по простому пути, просто обошел некоторые условия. Может кто-то поможет их поправить, чтобы | ||
+ | работало полностью со всеми условиями. | ||
+ | |||
+ | Вот исправленные скрипты с ремарками там, где я менял код: | ||
+ | |||
+ | '''Событие "Таймер"''' | ||
+ | <source lang="java"> | ||
+ | import java.sql.*; | ||
+ | import java.util.*; | ||
+ | |||
+ | // Мои добавления | ||
+ | import bitel.billing.server.ipn.bean.*; | ||
+ | import ru.bitel.bgbilling.server.util.ModuleSetup; | ||
+ | // | ||
+ | |||
+ | import bitel.billing.server.contract.bean.*; | ||
+ | import bitel.billing.server.tariff.*; | ||
+ | import bitel.billing.server.util.*; | ||
+ | import bitel.billing.common.KernelConst; | ||
+ | |||
+ | // код услуги | ||
+ | sid = 25; | ||
+ | // код экземпляра модуля | ||
+ | mid = 15; | ||
+ | //Группа "Недостаточно средств" | ||
+ | GROUP_ERROR_BALANCE = 16; | ||
+ | |||
+ | if( event.getFlag() != 1 ) { | ||
+ | return; | ||
+ | }; | ||
+ | |||
+ | cid = event.getContractID(); | ||
+ | DateNow = new GregorianCalendar(); | ||
+ | contract = new ContractManager(con).getContractByID(cid); | ||
+ | if (contract == null){ | ||
+ | return; | ||
+ | }; | ||
+ | BalanceMode = contract.getBalanceMode(); | ||
+ | if (BalanceMode == 0){ | ||
+ | //Пропускаем тех кто работает по факту | ||
+ | return; | ||
+ | }; | ||
+ | contract_status_manager = new ContractStatusManager(con); | ||
+ | status = contract_status_manager.getStatus(cid, DateNow); | ||
+ | contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; | ||
+ | if (status != null) | ||
+ | { | ||
+ | contract_status = status.getStatus(); | ||
+ | } | ||
+ | |||
+ | if (contract_status == null) | ||
+ | { | ||
+ | contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; | ||
+ | }; | ||
+ | if (contract_status != KernelConst.CONTRACT_STATUS_ACTIVE) | ||
+ | { | ||
+ | //Пропускаем не активные договора | ||
+ | return; | ||
+ | }; | ||
+ | |||
+ | date_str=TimeUtils.format(DateNow, "yyyy-MM-dd"); | ||
+ | |||
+ | //Проверяем привязана ли услуга "абонплата" | ||
+ | abn_count = "0"; | ||
+ | query_check_abn = | ||
+ | " SELECT npay_service_object_"+mid+".col"+ | ||
+ | " FROM contract_service"+ | ||
+ | " LEFT JOIN npay_service_object_"+mid+ | ||
+ | " ON (contract_service.id=npay_service_object_"+mid+".csid)"+ | ||
+ | " WHERE (contract_service.date1 is NULL OR contract_service.date1<='"+date_str+"') AND"+ | ||
+ | " (contract_service.date2 is NULL OR contract_service.date2>='"+date_str+"') AND"+ | ||
+ | " contract_service.sid='"+sid+"' AND contract_service.cid='"+cid+"'"; | ||
+ | re_check_abn = con.prepareStatement(query_check_abn); | ||
+ | rs_check_abn = re_check_abn.executeQuery(); | ||
+ | while (rs_check_abn.next()) | ||
+ | { | ||
+ | if (rs_check_abn.getString(1) == null) | ||
+ | { | ||
+ | abn_count = "1"; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | abn_count = rs_check_abn.getString(1); | ||
+ | }; | ||
+ | }; | ||
+ | ////Это условие, почему-то, не работало и abn_count не было равно 1, даже когда абонплата была привязана | ||
+ | /// к договору. | ||
+ | abn_count = "1"; | ||
+ | /// | ||
+ | abn_count = Double.parseDouble(abn_count); | ||
+ | if (abn_count == 0) | ||
+ | { | ||
+ | //Услуга не найдена. | ||
+ | return; | ||
+ | }; | ||
+ | |||
+ | day_str=TimeUtils.format(DateNow, "dd"); | ||
+ | day = Double.parseDouble(day_str); | ||
+ | |||
+ | cost = null; | ||
+ | cost_type = null; | ||
+ | calc_mode = null; | ||
+ | calc_type = null; | ||
+ | // поиск параметров абонплаты | ||
+ | tts = new ContractManager( con ).getRealtimeTariffTreeSet( cid, DateNow, "npay", mid, true ); | ||
+ | for( TariffModuleTree tree : tts.getTreeList( DateNow ) ) | ||
+ | { | ||
+ | req_cost = new TariffRequest(); | ||
+ | req_cost.setRequestParam( "action", "calculate" ); | ||
+ | req_cost.setRequestParam( "sid", sid ); | ||
+ | req_cost.setRequestParam( "month_days", 1 ); | ||
+ | req_cost.setRequestParam( "period_days", 1 ); | ||
+ | req_cost.setRequestParam( "time", DateNow); | ||
+ | tree.processRequest( req_cost ); | ||
+ | cost = (Double)req_cost.getResponseParam( "cost" ); | ||
+ | cost_type = req_cost.getResponseParam( "cost_type" ); | ||
+ | |||
+ | req_calc_mode = new TariffRequest(); | ||
+ | req_calc_mode.setRequestParam( "action", "reset" ); | ||
+ | req_calc_mode.setRequestParam( "sid", sid ); | ||
+ | req_calc_mode.setRequestParam( "time", DateNow); | ||
+ | tree.processRequest( req_calc_mode ); | ||
+ | calc_mode = (String)req_calc_mode.getResponseParam( "calc_mode" ); | ||
+ | calc_type = req_calc_mode.getResponseParam( "calc_type" ); | ||
+ | }; | ||
+ | |||
+ | if (cost == null || calc_mode == null) | ||
+ | { | ||
+ | error ("Параметры абонплаты не найдены"); | ||
+ | return; | ||
+ | }; | ||
+ | if (calc_mode.indexOf("month") != -1 && day != 1) | ||
+ | { | ||
+ | //абонплату за месяц снимаем только 1-ого числа | ||
+ | return; | ||
+ | }; | ||
+ | if (cost == 0) | ||
+ | { | ||
+ | return; | ||
+ | }; | ||
+ | |||
+ | cost = cost*abn_count; | ||
+ | print ("cid="+cid); | ||
+ | balance = new BalanceUtils(con); | ||
+ | contract_balance = balance.getBalance (new Date(), cid); | ||
+ | contract_limit = contract.getBalanceLimit(); | ||
+ | print ("contract_balance="+contract_balance); | ||
+ | print ("contract_limit="+contract_limit); | ||
+ | print ("contract_abn="+cost); | ||
+ | |||
+ | // Тут я просто изменил под себя, т.е. клиент может вносить любую сумму | ||
+ | contract_balance_new = contract_balance + cost - cost; | ||
+ | contract_limit_new = cost / 30; | ||
+ | print ("contract_balance_new="+contract_balance_new); | ||
+ | print ("contract_limit_new="+contract_limit_new); | ||
+ | if (contract_balance_new >= contract_limit + contract_limit_new) | ||
+ | { | ||
+ | print ("Balance OK"); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | print ("Balance error"); | ||
+ | /// | ||
+ | |||
+ | contract_groups = contract.getGroups(); | ||
+ | contract_groups = contract_groups | 1L<<GROUP_ERROR_BALANCE; | ||
+ | |||
+ | query = "UPDATE contract SET gr=? WHERE id=?"; | ||
+ | psUpdate = con.prepareStatement( query ); | ||
+ | psUpdate.setLong( 1, contract_groups ); | ||
+ | psUpdate.setInt( 2, cid ); | ||
+ | psUpdate.executeUpdate(); | ||
+ | |||
+ | ContractStatus status = new ContractStatus(); | ||
+ | status.setContractId( cid ); | ||
+ | status.setDate1( DateNow ); | ||
+ | status.setDate2( null ); | ||
+ | status.setStatus( KernelConst.CONTRACT_STATUS_SUSPENDED ); | ||
+ | status.setComment( "Недостаточно средств" ); | ||
+ | |||
+ | // Тут выдавало ошибку, просто убрал | ||
+ | // status.setUserId( 0 ); | ||
+ | |||
+ | contract_status_manager.changeStatus( status ); | ||
+ | |||
+ | // Тут не менялось состояние шлюза, добавил код с форума | ||
+ | |||
+ | // Переводим шлюз в статус "заблокирован" | ||
+ | modset = new ModuleSetup(con, 1); | ||
+ | (new IPNContractStatusManager(con, 1, modset)).changeStatus(cid, 2, 0, true); | ||
+ | }; | ||
+ | </source> | ||
+ | |||
+ | '''Событие "Приход тлатежа"''' | ||
+ | |||
+ | <source lang="java"> | ||
+ | |||
+ | import java.sql.*; | ||
+ | import java.util.*; | ||
+ | |||
+ | import bitel.billing.server.contract.bean.*; | ||
+ | |||
+ | // Мои добавления | ||
+ | import bitel.billing.server.ipn.bean.*; | ||
+ | // | ||
+ | |||
+ | import bitel.billing.server.tariff.*; | ||
+ | import bitel.billing.server.util.*; | ||
+ | import bitel.billing.common.KernelConst; | ||
+ | import ru.bitel.bgbilling.server.util.ModuleSetup; | ||
+ | |||
+ | // код услуги | ||
+ | sid = 25; | ||
+ | // код экземпляра модуля | ||
+ | mid = 15; | ||
+ | //Группа "Недостаточно средств" | ||
+ | GROUP_ERROR_BALANCE = 16; | ||
+ | |||
+ | DateNow = new GregorianCalendar(); | ||
+ | cid = event.getContractID(); | ||
+ | contract = new ContractManager(con).getContractByID(cid); | ||
+ | contract_groups = contract.getGroups(); | ||
+ | if ((contract_groups & (1L<<GROUP_ERROR_BALANCE)) == 0) | ||
+ | { | ||
+ | return; | ||
+ | }; | ||
+ | |||
+ | BalanceMode = contract.getBalanceMode(); | ||
+ | if (BalanceMode == 0){ | ||
+ | //Пропускаем тех кто работает по факту | ||
+ | return; | ||
+ | }; | ||
+ | |||
+ | contract_status_manager = new ContractStatusManager(con); | ||
+ | status = contract_status_manager.getStatus(cid, DateNow); | ||
+ | contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; | ||
+ | if (status != null) | ||
+ | { | ||
+ | contract_status = status.getStatus(); | ||
+ | } | ||
+ | |||
+ | if (contract_status == null) | ||
+ | { | ||
+ | contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; | ||
+ | }; | ||
+ | |||
+ | date_str=TimeUtils.format(DateNow, "yyyy-MM-dd"); | ||
+ | |||
+ | //Проверяем привязана ли услуга "абонплата" | ||
+ | abn_count = "0"; | ||
+ | query_check_abn = | ||
+ | " SELECT npay_service_object_"+mid+".col"+ | ||
+ | " FROM contract_service"+ | ||
+ | " LEFT JOIN npay_service_object_"+mid+ | ||
+ | " ON (contract_service.id=npay_service_object_"+mid+".csid)"+ | ||
+ | " WHERE (contract_service.date1 is NULL OR contract_service.date1<='"+date_str+"') AND"+ | ||
+ | " (contract_service.date2 is NULL OR contract_service.date2>='"+date_str+"') AND"+ | ||
+ | " contract_service.sid='"+sid+"' AND contract_service.cid='"+cid+"'"; | ||
+ | re_check_abn = con.prepareStatement(query_check_abn); | ||
+ | rs_check_abn = re_check_abn.executeQuery(); | ||
+ | while (rs_check_abn.next()) | ||
+ | { | ||
+ | if (rs_check_abn.getString(1) == null) | ||
+ | { | ||
+ | abn_count = "1"; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | abn_count = rs_check_abn.getString(1); | ||
+ | }; | ||
+ | }; | ||
+ | ////Это условие, почему-то, не работало и abn_count не было равно 1, даже когда абонплата была привязана | ||
+ | /// к договору. | ||
+ | abn_count = "1"; | ||
+ | /// | ||
+ | abn_count = Double.parseDouble(abn_count); | ||
+ | if (abn_count == 0) | ||
+ | { | ||
+ | //Услуга не найдена. | ||
+ | return; | ||
+ | }; | ||
+ | |||
+ | cost = null; | ||
+ | cost_type = null; | ||
+ | calc_mode = null; | ||
+ | calc_type = null; | ||
+ | // поиск параметров абонплаты | ||
+ | tts = new ContractManager( con ).getRealtimeTariffTreeSet( cid, DateNow, "npay", mid, true ); | ||
+ | for( TariffModuleTree tree : tts.getTreeList( DateNow ) ) | ||
+ | { | ||
+ | req_cost = new TariffRequest(); | ||
+ | req_cost.setRequestParam( "action", "calculate" ); | ||
+ | req_cost.setRequestParam( "sid", sid ); | ||
+ | req_cost.setRequestParam( "month_days", 1 ); | ||
+ | req_cost.setRequestParam( "period_days", 1 ); | ||
+ | req_cost.setRequestParam( "time", DateNow); | ||
+ | tree.processRequest( req_cost ); | ||
+ | cost = (Double)req_cost.getResponseParam( "cost" ); | ||
+ | cost_type = req_cost.getResponseParam( "cost_type" ); | ||
+ | |||
+ | req_calc_mode = new TariffRequest(); | ||
+ | req_calc_mode.setRequestParam( "action", "reset" ); | ||
+ | req_calc_mode.setRequestParam( "sid", sid ); | ||
+ | req_calc_mode.setRequestParam( "time", DateNow); | ||
+ | tree.processRequest( req_calc_mode ); | ||
+ | calc_mode = (String)req_calc_mode.getResponseParam( "calc_mode" ); | ||
+ | calc_type = req_calc_mode.getResponseParam( "calc_type" ); | ||
+ | }; | ||
+ | |||
+ | if (cost == null || calc_mode == null) | ||
+ | { | ||
+ | error ("Параметры абонплаты не найдены"); | ||
+ | return; | ||
+ | }; | ||
+ | if (calc_mode.indexOf("day") != -1) | ||
+ | { | ||
+ | //При снятии абонплаты за день клиент должен оплатить как минимум за 30 дней | ||
+ | |||
+ | cost = cost*abn_count; | ||
+ | // cost = cost*abn_count*30; | ||
+ | }; | ||
+ | if (calc_mode.indexOf("month") != -1) | ||
+ | { | ||
+ | cost = cost*abn_count; | ||
+ | }; | ||
+ | print ("cid="+cid); | ||
+ | balance = new BalanceUtils(con); | ||
+ | contract_balance = balance.getBalance (new Date(), cid); | ||
+ | contract_limit = contract.getBalanceLimit(); | ||
+ | print ("contract_balance="+contract_balance); | ||
+ | print ("contract_limit="+contract_limit); | ||
+ | print ("contract_abn="+cost); | ||
+ | |||
+ | // Тут я просто изменил под себя, т.е. клиент может вносить любую сумму | ||
+ | contract_balance_new = contract_balance + cost - cost; | ||
+ | |||
+ | print ("contract_balance_new="+contract_balance_new); | ||
+ | |||
+ | if (contract_balance_new >= contract_limit) | ||
+ | |||
+ | { | ||
+ | print ("Balance OK"); | ||
+ | |||
+ | contract_groups = contract_groups & ~(1L<<GROUP_ERROR_BALANCE); | ||
+ | |||
+ | query = "UPDATE contract SET gr=? WHERE id=?"; | ||
+ | psUpdate = con.prepareStatement( query ); | ||
+ | psUpdate.setLong( 1, contract_groups ); | ||
+ | psUpdate.setInt( 2, cid ); | ||
+ | psUpdate.executeUpdate(); | ||
+ | |||
+ | if (contract_status != KernelConst.CONTRACT_STATUS_ACTIVE) | ||
+ | { | ||
+ | ContractStatus status = new ContractStatus(); | ||
+ | status.setContractId( cid ); | ||
+ | status.setDate1( DateNow ); | ||
+ | status.setDate2( null ); | ||
+ | status.setStatus( KernelConst.CONTRACT_STATUS_ACTIVE ); | ||
+ | status.setComment( "Автоматически после оплаты" ); | ||
+ | |||
+ | |||
+ | // Тут выдавало ошибку, просто убрал | ||
+ | // status.setUserId( 0 ); | ||
+ | |||
+ | contract_status_manager.changeStatus( status ); | ||
+ | |||
+ | // Тут не менялось состояние шлюза, добавил код с форума | ||
+ | |||
+ | // Переводим шлюз в статус "открыт" | ||
+ | modset = new ModuleSetup(con, 1); | ||
+ | (new IPNContractStatusManager(con, 1, modset)).changeStatus(cid, 0, 0, true); | ||
+ | |||
+ | }; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | print ("Balance error"); | ||
+ | }; | ||
+ | </source> | ||
+ | |||
+ | |||
+ | Остальные два скрипта не смотрел, не использую пока. | ||
+ | Буду признателен, если автор скриптов подправит их более профессионально. |
Текущая версия на 11:06, 26 сентября 2009
Приведу пример набора скриптов, для снятия абонентской платы в договорах, работающий по предоплате.
Описание: В начале дня, до начисление абонентской платы, генерируется событие таймера с flag=1. По этому событию запускается скрипт проверки баланса. Если текущий баланс договора не позволяет списать абонентскую плату, то договор приостанавливается с комментарием "Недостаточно средств" и добавляется в группу "Недостаточно средств". Далее для договоров, входящих к группу "Недостаточно средств", при приходе платежа делается проверка. Если текущий баланс позволяет списать абонентскую плату, то статус договора меняется на "активен" с комментарием "Автоматически после оплаты" и договор исключается из группы "Недостаточно средств". Так же для договоров, входящих в группу "Недостаточно средств", есть возможность выполнить доп. действие "Принудительно разблокировать договор". Если его выполнить, то статус договора будет изменен на "активен" с комментарием "Принудительно из доп. действия" и договор будет исключен из группы "Недостаточно средств".
Событие "Таймер"
import java.sql.*; import java.util.*; import bitel.billing.server.contract.bean.*; import bitel.billing.server.tariff.*; import bitel.billing.server.util.*; import bitel.billing.common.KernelConst; // код услуги sid = 23; // код экземпляра модуля mid = 7; //Группа "Недостаточно средств" GROUP_ERROR_BALANCE = 19; if( event.getFlag() != 1 ) { return; }; cid = event.getContractID(); DateNow = new GregorianCalendar(); contract = new ContractManager(con).getContractByID(cid); if (contract == null){ return; }; BalanceMode = contract.getBalanceMode(); if (BalanceMode == 0){ //Пропускаем тех кто работает по факту return; }; contract_status_manager = new ContractStatusManager(con); status = contract_status_manager.getStatus(cid, DateNow); contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; if (status != null) { contract_status = status.getStatus(); } if (contract_status == null) { contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; }; if (contract_status != KernelConst.CONTRACT_STATUS_ACTIVE) { //Пропускаем не активные договора return; }; date_str=TimeUtils.format(DateNow, "yyyy-MM-dd"); //Проверяем привязана ли услуга "абонплата" abn_count = "0"; query_check_abn = " SELECT npay_service_object_"+mid+".col"+ " FROM contract_service"+ " LEFT JOIN npay_service_object_"+mid+ " ON (contract_service.id=npay_service_object_"+mid+".csid)"+ " WHERE (contract_service.date1 is NULL OR contract_service.date1<='"+date_str+"') AND"+ " (contract_service.date2 is NULL OR contract_service.date2>='"+date_str+"') AND"+ " contract_service.sid='"+sid+"' AND contract_service.cid='"+cid+"'"; re_check_abn = con.prepareStatement(query_check_abn); rs_check_abn = re_check_abn.executeQuery(); while (rs_check_abn.next()) { if (rs_check_abn.getString(1) == null) { abn_count = "1"; } else { abn_count = rs_check_abn.getString(1); }; }; abn_count = Double.parseDouble(abn_count); if (abn_count == 0) { //Услуга не найдена. return; }; day_str=TimeUtils.format(DateNow, "dd"); day = Double.parseDouble(day_str); cost = null; cost_type = null; calc_mode = null; calc_type = null; // поиск параметров абонплаты tts = new ContractManager( con ).getRealtimeTariffTreeSet( cid, DateNow, "npay", mid, true ); for( TariffModuleTree tree : tts.getTreeList( DateNow ) ) { req_cost = new TariffRequest(); req_cost.setRequestParam( "action", "calculate" ); req_cost.setRequestParam( "sid", sid ); req_cost.setRequestParam( "month_days", 1 ); req_cost.setRequestParam( "period_days", 1 ); req_cost.setRequestParam( "time", DateNow); tree.processRequest( req_cost ); cost = (Double)req_cost.getResponseParam( "cost" ); cost_type = req_cost.getResponseParam( "cost_type" ); req_calc_mode = new TariffRequest(); req_calc_mode.setRequestParam( "action", "reset" ); req_calc_mode.setRequestParam( "sid", sid ); req_calc_mode.setRequestParam( "time", DateNow); tree.processRequest( req_calc_mode ); calc_mode = (String)req_calc_mode.getResponseParam( "calc_mode" ); calc_type = req_calc_mode.getResponseParam( "calc_type" ); }; if (cost == null || calc_mode == null) { error ("Параметры абонплаты не найдены"); return; }; if (calc_mode.indexOf("month") != -1 && day != 1) { //абонплату за месяц снимаем только 1-ого числа return; }; if (cost == 0) { return; }; cost = cost*abn_count; print ("cid="+cid); balance = new BalanceUtils(con); contract_balance = balance.getBalance (new Date(), cid); contract_limit = contract.getBalanceLimit(); print ("contract_balance="+contract_balance); print ("contract_limit="+contract_limit); print ("contract_abn="+cost); contract_balance_new = contract_balance - cost; print ("contract_balance_new="+contract_balance_new); if (contract_balance_new >= contract_limit) { print ("Balance OK"); } else { print ("Balance error"); contract_groups = contract.getGroups(); contract_groups = contract_groups | 1L<<GROUP_ERROR_BALANCE; query = "UPDATE contract SET gr=? WHERE id=?"; psUpdate = con.prepareStatement( query ); psUpdate.setLong( 1, contract_groups ); psUpdate.setInt( 2, cid ); psUpdate.executeUpdate(); ContractStatus status = new ContractStatus(); status.setContractId( cid ); status.setDate1( DateNow ); status.setDate2( null ); status.setStatus( KernelConst.CONTRACT_STATUS_SUSPENDED ); status.setComment( "Недостаточно средств" ); status.setUserId( 0 ); contract_status_manager.changeStatus( status ); };
Событие "Приход тлатежа"
import java.sql.*; import java.util.*; import bitel.billing.server.contract.bean.*; import bitel.billing.server.tariff.*; import bitel.billing.server.util.*; import bitel.billing.common.KernelConst; // код услуги sid = 23; // код экземпляра модуля mid = 7; //Группа "Недостаточно средств" GROUP_ERROR_BALANCE = 19; DateNow = new GregorianCalendar(); cid = event.getContractID(); contract = new ContractManager(con).getContractByID(cid); contract_groups = contract.getGroups(); if ((contract_groups & (1L<<GROUP_ERROR_BALANCE)) == 0) { return; }; BalanceMode = contract.getBalanceMode(); if (BalanceMode == 0){ //Пропускаем тех кто работает по факту return; }; contract_status_manager = new ContractStatusManager(con); status = contract_status_manager.getStatus(cid, DateNow); contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; if (status != null) { contract_status = status.getStatus(); } if (contract_status == null) { contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; }; date_str=TimeUtils.format(DateNow, "yyyy-MM-dd"); //Проверяем привязана ли услуга "абонплата" abn_count = "0"; query_check_abn = " SELECT npay_service_object_"+mid+".col"+ " FROM contract_service"+ " LEFT JOIN npay_service_object_"+mid+ " ON (contract_service.id=npay_service_object_"+mid+".csid)"+ " WHERE (contract_service.date1 is NULL OR contract_service.date1<='"+date_str+"') AND"+ " (contract_service.date2 is NULL OR contract_service.date2>='"+date_str+"') AND"+ " contract_service.sid='"+sid+"' AND contract_service.cid='"+cid+"'"; re_check_abn = con.prepareStatement(query_check_abn); rs_check_abn = re_check_abn.executeQuery(); while (rs_check_abn.next()) { if (rs_check_abn.getString(1) == null) { abn_count = "1"; } else { abn_count = rs_check_abn.getString(1); }; }; abn_count = Double.parseDouble(abn_count); if (abn_count == 0) { //Услуга не найдена. return; }; cost = null; cost_type = null; calc_mode = null; calc_type = null; // поиск параметров абонплаты tts = new ContractManager( con ).getRealtimeTariffTreeSet( cid, DateNow, "npay", mid, true ); for( TariffModuleTree tree : tts.getTreeList( DateNow ) ) { req_cost = new TariffRequest(); req_cost.setRequestParam( "action", "calculate" ); req_cost.setRequestParam( "sid", sid ); req_cost.setRequestParam( "month_days", 1 ); req_cost.setRequestParam( "period_days", 1 ); req_cost.setRequestParam( "time", DateNow); tree.processRequest( req_cost ); cost = (Double)req_cost.getResponseParam( "cost" ); cost_type = req_cost.getResponseParam( "cost_type" ); req_calc_mode = new TariffRequest(); req_calc_mode.setRequestParam( "action", "reset" ); req_calc_mode.setRequestParam( "sid", sid ); req_calc_mode.setRequestParam( "time", DateNow); tree.processRequest( req_calc_mode ); calc_mode = (String)req_calc_mode.getResponseParam( "calc_mode" ); calc_type = req_calc_mode.getResponseParam( "calc_type" ); }; if (cost == null || calc_mode == null) { error ("Параметры абонплаты не найдены"); return; }; if (calc_mode.indexOf("day") != -1) { //При снятии абонплаты за день клиент должен оплатить как минимум за 30 дней cost = cost*abn_count*30; }; if (calc_mode.indexOf("month") != -1) { cost = cost*abn_count; }; print ("cid="+cid); balance = new BalanceUtils(con); contract_balance = balance.getBalance (new Date(), cid); contract_limit = contract.getBalanceLimit(); print ("contract_balance="+contract_balance); print ("contract_limit="+contract_limit); print ("contract_abn="+cost); contract_balance_new = contract_balance - cost; print ("contract_balance_new="+contract_balance_new); if (contract_balance_new >= contract_limit) { print ("Balance OK"); contract_groups = contract_groups & ~(1L<<GROUP_ERROR_BALANCE); query = "UPDATE contract SET gr=? WHERE id=?"; psUpdate = con.prepareStatement( query ); psUpdate.setLong( 1, contract_groups ); psUpdate.setInt( 2, cid ); psUpdate.executeUpdate(); if (contract_status != KernelConst.CONTRACT_STATUS_ACTIVE) { ContractStatus status = new ContractStatus(); status.setContractId( cid ); status.setDate1( DateNow ); status.setDate2( null ); status.setStatus( KernelConst.CONTRACT_STATUS_ACTIVE ); status.setComment( "Автоматически после оплаты" ); status.setUserId( 0 ); contract_status_manager.changeStatus( status ); }; } else { print ("Balance error"); };
Событие "Обработка доп. действия для договора"
import java.sql.*; import java.util.*; import bitel.billing.server.contract.bean.*; import bitel.billing.common.KernelConst; if (event.getActionId() != 21) { print("skipped"); return; } //Группа "Недостаточно средств" GROUP_ERROR_BALANCE = 19; DateNow = new GregorianCalendar(); cid = event.getContractID(); contract = new ContractManager(con).getContractByID(cid); contract_groups = contract.getGroups(); contract_status_manager = new ContractStatusManager(con); status = contract_status_manager.getStatus(cid, DateNow); contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; if (status != null) { contract_status = status.getStatus(); } if (contract_status == null) { contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; }; contract_groups = contract_groups & ~(1L<<GROUP_ERROR_BALANCE); query = "UPDATE contract SET gr=? WHERE id=?"; psUpdate = con.prepareStatement( query ); psUpdate.setLong( 1, contract_groups ); psUpdate.setInt( 2, cid ); psUpdate.executeUpdate(); if (contract_status != KernelConst.CONTRACT_STATUS_ACTIVE) { ContractStatus status = new ContractStatus(); status.setContractId( cid ); status.setDate1( DateNow ); status.setDate2( null ); status.setStatus( KernelConst.CONTRACT_STATUS_ACTIVE ); status.setComment( "Принудительно из доп. действия" ); status.setUserId( 0 ); contract_status_manager.changeStatus( status ); };
Событие "Получить список доп. действия для договора"
import bitel.billing.server.contract.bean.*; //Группа "Недостаточно средств" GROUP_ERROR_BALANCE = 19; cid = event.getContractID(); contract = new ContractManager(con).getContractByID(cid); contract_groups = contract.getGroups(); contract_is_group_error_balance = (contract_groups & (1L<<GROUP_ERROR_BALANCE)) > 0; if (contract_is_group_error_balance) { event.addAction( 21, "Принудительно разблокировать договор" ); };
В новой версии билинга (4.6) эти скрипты не работают. Пришлось немного изменить, чтобы заработали. В яве не спец, поэтому пошел по простому пути, просто обошел некоторые условия. Может кто-то поможет их поправить, чтобы работало полностью со всеми условиями.
Вот исправленные скрипты с ремарками там, где я менял код:
Событие "Таймер"
import java.sql.*; import java.util.*; // Мои добавления import bitel.billing.server.ipn.bean.*; import ru.bitel.bgbilling.server.util.ModuleSetup; // import bitel.billing.server.contract.bean.*; import bitel.billing.server.tariff.*; import bitel.billing.server.util.*; import bitel.billing.common.KernelConst; // код услуги sid = 25; // код экземпляра модуля mid = 15; //Группа "Недостаточно средств" GROUP_ERROR_BALANCE = 16; if( event.getFlag() != 1 ) { return; }; cid = event.getContractID(); DateNow = new GregorianCalendar(); contract = new ContractManager(con).getContractByID(cid); if (contract == null){ return; }; BalanceMode = contract.getBalanceMode(); if (BalanceMode == 0){ //Пропускаем тех кто работает по факту return; }; contract_status_manager = new ContractStatusManager(con); status = contract_status_manager.getStatus(cid, DateNow); contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; if (status != null) { contract_status = status.getStatus(); } if (contract_status == null) { contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; }; if (contract_status != KernelConst.CONTRACT_STATUS_ACTIVE) { //Пропускаем не активные договора return; }; date_str=TimeUtils.format(DateNow, "yyyy-MM-dd"); //Проверяем привязана ли услуга "абонплата" abn_count = "0"; query_check_abn = " SELECT npay_service_object_"+mid+".col"+ " FROM contract_service"+ " LEFT JOIN npay_service_object_"+mid+ " ON (contract_service.id=npay_service_object_"+mid+".csid)"+ " WHERE (contract_service.date1 is NULL OR contract_service.date1<='"+date_str+"') AND"+ " (contract_service.date2 is NULL OR contract_service.date2>='"+date_str+"') AND"+ " contract_service.sid='"+sid+"' AND contract_service.cid='"+cid+"'"; re_check_abn = con.prepareStatement(query_check_abn); rs_check_abn = re_check_abn.executeQuery(); while (rs_check_abn.next()) { if (rs_check_abn.getString(1) == null) { abn_count = "1"; } else { abn_count = rs_check_abn.getString(1); }; }; ////Это условие, почему-то, не работало и abn_count не было равно 1, даже когда абонплата была привязана /// к договору. abn_count = "1"; /// abn_count = Double.parseDouble(abn_count); if (abn_count == 0) { //Услуга не найдена. return; }; day_str=TimeUtils.format(DateNow, "dd"); day = Double.parseDouble(day_str); cost = null; cost_type = null; calc_mode = null; calc_type = null; // поиск параметров абонплаты tts = new ContractManager( con ).getRealtimeTariffTreeSet( cid, DateNow, "npay", mid, true ); for( TariffModuleTree tree : tts.getTreeList( DateNow ) ) { req_cost = new TariffRequest(); req_cost.setRequestParam( "action", "calculate" ); req_cost.setRequestParam( "sid", sid ); req_cost.setRequestParam( "month_days", 1 ); req_cost.setRequestParam( "period_days", 1 ); req_cost.setRequestParam( "time", DateNow); tree.processRequest( req_cost ); cost = (Double)req_cost.getResponseParam( "cost" ); cost_type = req_cost.getResponseParam( "cost_type" ); req_calc_mode = new TariffRequest(); req_calc_mode.setRequestParam( "action", "reset" ); req_calc_mode.setRequestParam( "sid", sid ); req_calc_mode.setRequestParam( "time", DateNow); tree.processRequest( req_calc_mode ); calc_mode = (String)req_calc_mode.getResponseParam( "calc_mode" ); calc_type = req_calc_mode.getResponseParam( "calc_type" ); }; if (cost == null || calc_mode == null) { error ("Параметры абонплаты не найдены"); return; }; if (calc_mode.indexOf("month") != -1 && day != 1) { //абонплату за месяц снимаем только 1-ого числа return; }; if (cost == 0) { return; }; cost = cost*abn_count; print ("cid="+cid); balance = new BalanceUtils(con); contract_balance = balance.getBalance (new Date(), cid); contract_limit = contract.getBalanceLimit(); print ("contract_balance="+contract_balance); print ("contract_limit="+contract_limit); print ("contract_abn="+cost); // Тут я просто изменил под себя, т.е. клиент может вносить любую сумму contract_balance_new = contract_balance + cost - cost; contract_limit_new = cost / 30; print ("contract_balance_new="+contract_balance_new); print ("contract_limit_new="+contract_limit_new); if (contract_balance_new >= contract_limit + contract_limit_new) { print ("Balance OK"); } else { print ("Balance error"); /// contract_groups = contract.getGroups(); contract_groups = contract_groups | 1L<<GROUP_ERROR_BALANCE; query = "UPDATE contract SET gr=? WHERE id=?"; psUpdate = con.prepareStatement( query ); psUpdate.setLong( 1, contract_groups ); psUpdate.setInt( 2, cid ); psUpdate.executeUpdate(); ContractStatus status = new ContractStatus(); status.setContractId( cid ); status.setDate1( DateNow ); status.setDate2( null ); status.setStatus( KernelConst.CONTRACT_STATUS_SUSPENDED ); status.setComment( "Недостаточно средств" ); // Тут выдавало ошибку, просто убрал // status.setUserId( 0 ); contract_status_manager.changeStatus( status ); // Тут не менялось состояние шлюза, добавил код с форума // Переводим шлюз в статус "заблокирован" modset = new ModuleSetup(con, 1); (new IPNContractStatusManager(con, 1, modset)).changeStatus(cid, 2, 0, true); };
Событие "Приход тлатежа"
import java.sql.*; import java.util.*; import bitel.billing.server.contract.bean.*; // Мои добавления import bitel.billing.server.ipn.bean.*; // import bitel.billing.server.tariff.*; import bitel.billing.server.util.*; import bitel.billing.common.KernelConst; import ru.bitel.bgbilling.server.util.ModuleSetup; // код услуги sid = 25; // код экземпляра модуля mid = 15; //Группа "Недостаточно средств" GROUP_ERROR_BALANCE = 16; DateNow = new GregorianCalendar(); cid = event.getContractID(); contract = new ContractManager(con).getContractByID(cid); contract_groups = contract.getGroups(); if ((contract_groups & (1L<<GROUP_ERROR_BALANCE)) == 0) { return; }; BalanceMode = contract.getBalanceMode(); if (BalanceMode == 0){ //Пропускаем тех кто работает по факту return; }; contract_status_manager = new ContractStatusManager(con); status = contract_status_manager.getStatus(cid, DateNow); contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; if (status != null) { contract_status = status.getStatus(); } if (contract_status == null) { contract_status = KernelConst.CONTRACT_STATUS_ACTIVE; }; date_str=TimeUtils.format(DateNow, "yyyy-MM-dd"); //Проверяем привязана ли услуга "абонплата" abn_count = "0"; query_check_abn = " SELECT npay_service_object_"+mid+".col"+ " FROM contract_service"+ " LEFT JOIN npay_service_object_"+mid+ " ON (contract_service.id=npay_service_object_"+mid+".csid)"+ " WHERE (contract_service.date1 is NULL OR contract_service.date1<='"+date_str+"') AND"+ " (contract_service.date2 is NULL OR contract_service.date2>='"+date_str+"') AND"+ " contract_service.sid='"+sid+"' AND contract_service.cid='"+cid+"'"; re_check_abn = con.prepareStatement(query_check_abn); rs_check_abn = re_check_abn.executeQuery(); while (rs_check_abn.next()) { if (rs_check_abn.getString(1) == null) { abn_count = "1"; } else { abn_count = rs_check_abn.getString(1); }; }; ////Это условие, почему-то, не работало и abn_count не было равно 1, даже когда абонплата была привязана /// к договору. abn_count = "1"; /// abn_count = Double.parseDouble(abn_count); if (abn_count == 0) { //Услуга не найдена. return; }; cost = null; cost_type = null; calc_mode = null; calc_type = null; // поиск параметров абонплаты tts = new ContractManager( con ).getRealtimeTariffTreeSet( cid, DateNow, "npay", mid, true ); for( TariffModuleTree tree : tts.getTreeList( DateNow ) ) { req_cost = new TariffRequest(); req_cost.setRequestParam( "action", "calculate" ); req_cost.setRequestParam( "sid", sid ); req_cost.setRequestParam( "month_days", 1 ); req_cost.setRequestParam( "period_days", 1 ); req_cost.setRequestParam( "time", DateNow); tree.processRequest( req_cost ); cost = (Double)req_cost.getResponseParam( "cost" ); cost_type = req_cost.getResponseParam( "cost_type" ); req_calc_mode = new TariffRequest(); req_calc_mode.setRequestParam( "action", "reset" ); req_calc_mode.setRequestParam( "sid", sid ); req_calc_mode.setRequestParam( "time", DateNow); tree.processRequest( req_calc_mode ); calc_mode = (String)req_calc_mode.getResponseParam( "calc_mode" ); calc_type = req_calc_mode.getResponseParam( "calc_type" ); }; if (cost == null || calc_mode == null) { error ("Параметры абонплаты не найдены"); return; }; if (calc_mode.indexOf("day") != -1) { //При снятии абонплаты за день клиент должен оплатить как минимум за 30 дней cost = cost*abn_count; // cost = cost*abn_count*30; }; if (calc_mode.indexOf("month") != -1) { cost = cost*abn_count; }; print ("cid="+cid); balance = new BalanceUtils(con); contract_balance = balance.getBalance (new Date(), cid); contract_limit = contract.getBalanceLimit(); print ("contract_balance="+contract_balance); print ("contract_limit="+contract_limit); print ("contract_abn="+cost); // Тут я просто изменил под себя, т.е. клиент может вносить любую сумму contract_balance_new = contract_balance + cost - cost; print ("contract_balance_new="+contract_balance_new); if (contract_balance_new >= contract_limit) { print ("Balance OK"); contract_groups = contract_groups & ~(1L<<GROUP_ERROR_BALANCE); query = "UPDATE contract SET gr=? WHERE id=?"; psUpdate = con.prepareStatement( query ); psUpdate.setLong( 1, contract_groups ); psUpdate.setInt( 2, cid ); psUpdate.executeUpdate(); if (contract_status != KernelConst.CONTRACT_STATUS_ACTIVE) { ContractStatus status = new ContractStatus(); status.setContractId( cid ); status.setDate1( DateNow ); status.setDate2( null ); status.setStatus( KernelConst.CONTRACT_STATUS_ACTIVE ); status.setComment( "Автоматически после оплаты" ); // Тут выдавало ошибку, просто убрал // status.setUserId( 0 ); contract_status_manager.changeStatus( status ); // Тут не менялось состояние шлюза, добавил код с форума // Переводим шлюз в статус "открыт" modset = new ModuleSetup(con, 1); (new IPNContractStatusManager(con, 1, modset)).changeStatus(cid, 0, 0, true); }; } else { print ("Balance error"); };
Остальные два скрипта не смотрел, не использую пока.
Буду признателен, если автор скриптов подправит их более профессионально.