Дебетовые абонплаты. Снятие штрафа за разблокировку.
Материал из BiTel WiKi
Версия от 11:45, 24 февраля 2010; Admin (Обсуждение | вклад)
Разработано для версии 5.0.
Ставятся задачи:
- Списание доп. расхода (штрафа) при автоматической разблокировке статуса дебетового договора по достаточному платежу. Стоимость штрафа запрашивается как стоимость RSCM услуги.
- Запрещение разблокировки в случае, если после разблокировки превышение остатка над лимитом составит менее определённой суммы, привязанной к конкретному тарифу (минимальный остаток).
При разблокировке снимается штраф, начисляется абонплата. Наработка, начисленная на замещающую услугу в период закрытия договора переносится в расход.
1. Создайте библиотеку скриптов с именем npay_debet и кодом, приведённым ниже. Скорректируйте константы с кодом экземпляра модуля RSCM и услугой, определяющей стоимость разблокировки.
import java.util.*; import java.math.*; import bitel.billing.server.contract.bean.*; import bitel.billing.server.tariff.*; // код экземпляра модуля RSCM RSCM_MID = 60; // код услуги модуля RSCM стоимость которой в тарифном плане задаёт штраф за разблокировку UNLOCK_RSCM_SERVICE = 118; class UnlockInfo { BigDecimal summa; int treeId; } public UnlockInfo getUnlockInfo( cid, conSlave ) { UnlockInfo result = null; contractManager = new ContractManager( conSlave ); contract = contractManager.getContractByID( cid ); if( contract == null ) { error( "Contract not found " + cid ); return result; } if( !contract.isIndepend() ) { error( "Supported only independ contracts" ); return result; } now = new GregorianCalendar(); tts = contractManager.getRealtimeTariffTreeSet( cid, now, "rscm", RSCM_MID, true ); tree = tts.getTree( now ); if( tree == null ) { error( "Not found RSCM tariff" ); return result; } req = new TariffRequest(); req.setRequestParam( "sid", UNLOCK_RSCM_SERVICE ); req.setRequestParam( "time", now ); tree.processRequest( req ); cost = req.getResponseParam( "cost" ); divisor = req.getResponseParam( "divisor" ); if( !req.wasAccepted() || cost == null || divisor == null || divisor <= 0 ) { error( "Incorrect result tariff RSCM request. cost: " + cost + "; devisor: " + devisor ); return result; } result = new UnlockInfo(); result.summa = new BigDecimal( cost / divisor ); result.treeId = tree.getTreeId(); return result; }
2. В скрипте поведения создайте функцию, обрабатывающую событие Запрос доп. расхода для открытия договора. Определите сумму минимальной предоплаты для каждого из тарифов.
import java.math.*; includeBGBS( "bgbs://ru.bitel.bgbilling.kernel.script.common.bean.ScriptLibrary/npay_debet" ); public void onEvent( event, setup, con, conSlave ) { unlockInfo = getUnlockInfo( event.getContractID(), conSlave ); if( unlockInfo == null ) { error( "Error take unlock info" ); return; } summa = unlockInfo.summa; print( "Cost for unlock: " + summa ); // здесь можно определить "довесок" в зависимости от кода тарифного дерева // код дерева можно получить выбором любого узла тарифного дерева и нажатием Ctrl+i, tree => <код дерева> if( unlockInfo.treeId == 226 ) { summa = summa.add( new BigDecimal( "11.20" ) ); print( "Add summa to " + summa + " by tariffTreeId" ); } else if ( unlockInfo.treeId == 15 ) { // } else if ( unlockInfo.treeId == 16 ) { // } event.setSumma( summa ); }
3. В скрипте поведения создайте функцию, обрабатывающую событие После открытия договора по платежу. Скорректируйте константы с типами расходов и кодом замещающей абонплаты.
import java.util.*; import java.math.*; import bitel.billing.server.contract.bean.*; import bitel.billing.server.tariff.*; // тип расхода, которым заносится списание-штраф за разблокировку UNLOCK_CHARGE_TYPE_ID = 38; // тип расхода, в который переносится наработка за преостановленный период по услуге, замещающей основную абонплату MOVED_LOCKED_ABON_CHARGE_TYPE_ID = 42; // код этой замещающей услуги LOCKED_ABON_SERVICE_ID = 129; includeBGBS( "bgbs://ru.bitel.bgbilling.kernel.script.common.bean.ScriptLibrary/npay_debet" ); public void onEvent( event, setup, con, conSlave ) { cid = event.getContractID(); unlockInfo = getUnlockInfo( cid, conSlave ); if( unlockInfo == null ) { error( "Error take unlock info" ); return; } summa = unlockInfo.summa; print( "Cost for unlock: " + summa ); bu = new BalanceUtils( con ); chm = new ChargeManager( con ); curdate = new Date(); // внесение расхода за разблокировку, полученного из RSCM тарифа charge = new Charge(); charge.setContractID( cid ); charge.setChargeTypeID( UNLOCK_CHARGE_TYPE_ID ); charge.setComment( "За разблокировку" ); charge.setChargeDate( curdate ); charge.setSumma( summa ); chm.updateCharge( charge ); // перенос наработки accountSumma = BigDecimal.ZERO; monthsForRecalc = new TreeSet(); query = "SELECT yy, mm, summa FROM contract_account WHERE cid=? AND sid=?"; ps = conSlave.prepareStatement( query ); ps.setInt( 1, cid ); ps.setInt( 2, LOCKED_ABON_SERVICE_ID ); rs = ps.executeQuery(); while( rs.next() ) { date = new GregorianCalendar( rs.getInt( 1 ), rs.getInt( 2 ) + 1, 1 ); monthsForRecalc.add( date ); accountSumma = accountSumma.add( rs.getBigDecimal( 3 ) ); } ps.close(); print( "Moving " + accountSumma + " on charge" ); // внесение расхода равного замещающей наработке charge = new Charge(); charge.setContractID( cid ); charge.setChargeTypeID( MOVED_LOCKED_ABON_CHARGE_TYPE_ID ); charge.setComment( "Перенесённая наработка" ); charge.setChargeDate( curdate ); charge.setSumma( accountSumma ); chm.updateCharge( charge ); // удаление наработки и обновление баланса месяцев, где она была удалена query = "DELETE FROM contract_account WHERE cid=? AND sid=?"; ps = con.prepareStatement( query ); ps.setInt( 1, cid ); ps.setInt( 2, LOCKED_ABON_SERVICE_ID ); ps.executeUpdate(); for( month : monthsForRecalc ) { bu.updateBalance( month.getTime(), cid ); } bu.updateBalance( curdate, cid ); }
Ссылки: