Допустим, мы хотим знать, сколько клиенту будет стоить на его тарифе следующие x МБ или y минут.
Код ниже позволяет получить эту цифру.
Указываем mid, cid, sid, amount (в байтах или секундах) и считаем.
Внимание! Скрипт не тестировался в боевых условиях, поэтому возможны накладки.
!!! Не запускать в контексте шедулера параллельно переобсчету сессий dialup !!!
!!! Не запускать в контексте радиус-сервера !!!
На вики выкладывать пока рано.
Класс DialupPrecalculator - копипаст кусков из SessionRecalculator.
Глобальный скрипт поведения:
Код:
import bitel.billing.server.tariff.*;
import java.util.*;
import java.util.Calendar;
import java.sql.*;
import bitel.billing.server.dialup.calc.ContractData;
import bitel.billing.server.dialup.calc.ContractDataStorage;
import ru.bitel.bgbilling.server.util.ModuleSetup;
import ru.bitel.bgbilling.server.util.ServerUtils;
import ru.bitel.bgbilling.server.util.Setup;
import bitel.billing.server.MaxTrafficCalculator;
import bitel.billing.server.tariff.detail.TariffDetailUtils;
import bitel.billing.server.dialup.calc.CalcPeriod;
import bitel.billing.server.dialup.bean.DialUpSessionUtils;
public void main( setup, con, conSlave )
{
int mid = 1;
int sid = 2;
int cid = 123;
long amount = 105906176; //101 MB
DialupPrecalculator precalculator = new DialupPrecalculator(mid, con, conSlave, setup);
Double cost = precalculator.precalculate(Calendar.getInstance(), Calendar.getInstance(), cid, sid, amount);
print(cost);
}
class DialupPrecalculator{
private String sids;
private ContractDataStorage contractDataStorage;
private int mid = -1;
private Calendar _date1;
private Calendar _date2;
private Calendar startMonth;
private Calendar endMonth;
private Connection con;
private Connection conSlave;
private ModuleSetup moduleSetup;
private transient Setup setup;
public DialupPrecalculator(int mid, java.sql.Connection con, java.sql.Connection conSlave, Setup setup){
this.mid = mid;
this.con = con;
this.conSlave = conSlave;
this.setup = setup;
this.moduleSetup = this.setup.getModuleSetup(Integer.valueOf(this.mid));
this.sids = MaxTrafficCalculator.getModuleServicesWithoutMaxTraf(this.con, this.mid, this.moduleSetup);
}
/**
* dtime - дата старта предполагаемого начисления,
* date2 - дата окончания начисления. Например, если мы вычисляем услугу типа "время", то date2=date1 + amount сек (не проверял)
*/
public Double precalculate(Calendar dtime, Calendar date2, int cid, int sid, long amount){
Double result = null;
this._date1 = dtime;
this._date2 = date2;
this.startMonth = ((Calendar)this._date1.clone());
this.startMonth.set(5, 1);
this.endMonth = ((Calendar)this._date2.clone());
this.endMonth.set(5, this.endMonth.getActualMaximum(5));
this.contractDataStorage = new ContractDataStorage(this.conSlave, this.mid, this.sids, this._date1, this._date2, this.startMonth, this.endMonth);
Set tariffDetailRangeTakeAllSet = TariffDetailUtils.getCostTypeRangeTakeAllIdSet(this.moduleSetup);
ContractData currentContractData = this.contractDataStorage.getContractData(cid, Integer.MAX_VALUE, dtime);
CalcPeriod period = currentContractData.getCalcPeriod(this._date1);
TariffTreeSet.TariffSetEntry tse = currentContractData.tts.getTreeEntry(this._date1);
if ((tse != null) && (period != null))
{
TariffRequest calcReq = new TariffRequest();
calcReq.setRequestParam("cid", Integer.valueOf(cid));
calcReq.setRequestParam("action", "calculate");
calcReq.setRequestParam("month_time", this.startMonth);
float servicePart = DialUpSessionUtils.getPart(period.start, period.end, sid, currentContractData.serviceRanges);
float tariffPart = tse.getPartOnPeriod(period.start, period.end);
float tariffPartSuspended = tse.getPartOnPeriod(period.start, period.end, currentContractData.suspendedPeriods);
calcReq.setRequestParam("sid", Integer.valueOf(sid));
calcReq.setRequestParam("time", dtime);
calcReq.setRequestParam("amount", Long.valueOf(amount));
calcReq.setRequestParam("period_end", period.end);
calcReq.setRequestParam("part_service", Float.valueOf(servicePart));
calcReq.setRequestParam("part_tariff", Float.valueOf(tariffPart));
calcReq.setRequestParam("part_tariff_suspended", Float.valueOf(tariffPartSuspended));
calcReq.setRequestParam("tariffOptions", currentContractData.tariffOptions);
calcReq.setRequestParam("costTypeRangeTakeAllSet", tariffDetailRangeTakeAllSet);
tse.getTree().processRequest(calcReq);
Float costAmount = (Float)calcReq.getResponseParam("costAmount");
Float dividend = (Float)calcReq.getResponseParam("cost");
Long divisor = (Long)calcReq.getResponseParam("divisor");
if (calcReq.wasAccepted())
{
Double cost = null;
if (costAmount != null)
{
cost = Double.valueOf(costAmount.doubleValue());
}
else if ((dividend != null) && (divisor != null) && (divisor.longValue() > 0L))
{
cost = Double.valueOf(amount * dividend.doubleValue() / divisor.longValue());
}
result = cost;
}
//Непонятно почему, но после вычисления нужно делать reset для корректного обсчета в следующий раз. Хотя в начале в getContractData делается тот же reset.
//Вместо этого в SessionRecalculator тут делается init
TariffRequest req = new TariffRequest();
req.setRequestParam("cid", Integer.valueOf(cid));
req.setRequestParam("action", "reset");
tse.getTree().processRequest(req);
}
return result;
}
}
Ушло 2 дня.