Снятие абонентской платы в дебитовых договорах
Материал из BiTel WiKi
Приведу пример набора скриптов, для снятия абонентской платы в договорах, работающий по предоплате.
Описание: В начале дня, до начисление абонентской платы, генерируется событие таймера с 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 = 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); ResultSet re_check_abn = re_check_abn.executeQuery(); while (re_check_abn.next()) { if (re_check_abn.getString(1) == null) { abn_count = "1"; } else { abn_count = re_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 = 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); ResultSet re_check_abn = re_check_abn.executeQuery(); while (re_check_abn.next()) { if (re_check_abn.getString(1) == null) { abn_count = "1"; } else { abn_count = re_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 = 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, "Принудительно разблокировать договор" ); };