Скрипт проверки баланса и отключения договора

Материал из BiTel WiKi

Перейти к: навигация, поиск
import java.sql.*;
import java.util.*;
import java.math.*;
 
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.tariff.*;
import bitel.billing.server.util.*;
import bitel.billing.common.KernelConst; 
import bitel.billing.server.script.bean.event.*;
 
import ru.bitel.bgbilling.plugins.crm.server.dao.*;
import ru.bitel.bgbilling.plugins.crm.common.model.*;
 
/*
Данный скрипт приостанавливает статус договра, когда исходящий остаток ниже абонентской платы.
Просьба изменить скрипт, то есть отвязать его от абонентской платы и приостанавливать договор по
исходящему балансу <-1000>, но при этом учитывать лимит. Если например у договора стоит лимит <-1200>,
а баланс меньше <-1000>, но больше <-1200> то с такими договорами ни чего не делаем и приостанавливаем
их только по достижению баланса меньше <-1200>. 
Также в скрипт добавить работу с кредитовыми договрами.
 
Когда договор приостановлен, то заносим в параметр договора (код 28, тип параметра "Дата") дату
пристановления договора "Дата фиксации долга". Приостановленный договр добавлем в группу
договоров "Должники" (код 8). Далее в CRM создаем задачу на обзвон должников (тип задачи 1),
группа решений (ID 3) с комментарием "Приостановлен сервером за долг".
 
+надо ещё удалить параметр "Дата погашения долга"
*/
/*
Приход платежа
Для договоров, входящих к группу "Должники", при приходе платежа делается проверка. Если при внесение платежа
баланс стал больше 0 (нуля), то удаляем дату приостановления договора "Дата фиксации долга"
(код 28, тип параметра "Дата") в параметре договора, создаем "Дата погашения долга" (код 20, тип параметра "Дата").
Закрываем в CRM задачу на обзвон должников с комментарием "Долг оплачен". Исключаем из группы договоров "Должники" (код 8). 
*/
 
// группы, для которых будет работать скрипт (номера)
int[] GROUPS ={29,1,2};
// значение порога, до которого лимит не действует (в рублях)
BigDecimal LIMITVALUE = new BigDecimal( -10 );
// ид параметра договора "Дата фиксации долга"
int DATE_OFF_PID = 30;
// ид параматра даты включения, "Дата погашения долга"
int DATE_ON_PID = 27;
//Группа "Недостаточно средств"
int GROUP_ERROR_BALANCE = 19;
// CRM - тип задачи
int CRM_TYPE = 3;
// CRM - группа решений
int CRM_GR = 3;
// если при внесении платежа баланс стал больше этой цифры, то делаем действия
BigDecimal LIMIT_TO_ON = new BigDecimal( -100 );
 
//----------
 
/**
 * Договор в одной ли из групп. Возвращается номер группы, в которой договор.
 * Или -1, если договор ни в одной из групп.
 */
int contractInGroup( Contract contract, int[] groups )
{
	for( int i=0; i<groups.length; i++ )
	{
		if( (contract.getGroups() & (1L<<groups[i])) != 0 )
		{
			return groups[i];
		}
	}
	return -1;
}
 
BalanceUtils bu = new BalanceUtils( con ); 
ContractParamUtils cpu = new ContractParamUtils( con );
ContractStatusManager contract_status_manager  = new ContractStatusManager( con );
RegisterTaskManager rtm = new RegisterTaskManager(con);
 
int cid = event.getContractID();
Calendar time = event.getGenerateTime();
Calendar DateNow = Calendar.getInstance();
Contract contract = new ContractManager(con).getContractByID(cid);
 
if (contract == null)
{
	print("договор не найден! пропускаем.");
	return;
}
else
{
	print("=> договор: "+contract.getTitle());
}
 
// проверям на вхождение в заданные группы
int cigr = contractInGroup( contract, GROUPS );
if (cigr == -1)
{
	print("договор не входит в нужные группы! пропускаем.");
	return;
}
else
{
	print("договор входит в группу #" + cigr);
}
 
// статус получаем	
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_balance = bu.getBalance (time.getTime(), cid);
print("баланс договора: "+contract_balance);
 
// если событие таймера
if( event instanceof bitel.billing.server.script.bean.event.TimerEvent && event.getFlag() == 1 )
{
	// проверяем статус
	// Пропускаем не активные договора
	if (contract_status != KernelConst.CONTRACT_STATUS_ACTIVE) 
	{		
		print("договор не активен! пропускаем.");
		return;
	}
 
	// берём лимит
	BigDecimal limit = contract.getBalanceLimit();
	print("лимит: "+limit);
	// может, надо поставить новый лимит?
	limit = limit.min(LIMITVALUE);
	print("значение по которому проверяем: "+limit);
 
	// соравниваем с лимитом
	if( contract_balance.compareTo( limit ) >= 0 )
	{
		print("баланс хороший");
	}
	else
	{
		print("баланс плохой");
 
		// суспендим договор
		ContractStatus status = new ContractStatus();
		status.setContractId( cid );
		status.setDate1( DateNow );
		status.setDate2( null );
		status.setStatus( KernelConst.CONTRACT_STATUS_SUSPENDED );
		status.setComment( "Недостаточно средств" );
		contract_status_manager.changeStatus( status, 0 );
 
		// ставим в аттрибут договора дату отключения
		cpu.setDateParam( cid, DATE_OFF_PID, time.getTime(), 0 );
		print( "off-date: " +  TimeUtils.formatDate( time ) );
 
		// удаляем дату включения (если есть)
		cpu.deleteDateParam( cid, DATE_ON_PID, 0 );
 
		// заносим в группу
		contract_groups = contract.getGroups();
		contract_groups = contract_groups | 1L<<GROUP_ERROR_BALANCE;
		psUpdate = con.prepareStatement( "UPDATE contract SET gr=? WHERE id=?" );
		psUpdate.setLong( 1, contract_groups );
		psUpdate.setInt( 2, cid );
		psUpdate.executeUpdate();
 
		// Далее в CRM создаем задачу на обзвон должников (тип задачи 1),
		// группа решений (ID 3) с комментарием "Приостановлен сервером за долг".
		RegisterTask task = new RegisterTask();
		task.setComment("Приостановлен сервером за долг");
		task.setContractID(cid);
		task.setCreateTime(time.getTime());
		task.setCreateUserID(0);
		task.setOpenTime(time.getTime());
		task.setOpenUserID(0);
		task.setGroupID(CRM_GR);
		task.setStatus(RegisterTask.STATUS_OPEN);
		task.setTypeID(CRM_TYPE);
		rtm.updateTask(task);
	}
}
 
// если событие прихода платежа
if( event instanceof bitel.billing.server.script.bean.event.PaymentEvent )
{
	// проверяем на вхождение в группу "должники"
	long contract_groups = contract.getGroups();
	if ((contract_groups & (1L<<GROUP_ERROR_BALANCE)) == 0)
	{
		print("договор не входит в группу \"должники\"! пропускаем.");
		return;
	}
 
	// сравниваем с лимитом
	if( contract_balance.compareTo( LIMIT_TO_ON ) > 0 )
	{
		print("баланс хороший (>"+LIMIT_TO_ON.toPlainString()+")");
 
		// удаляем из группы
		contract_groups = contract_groups & ~(1L<<GROUP_ERROR_BALANCE);
		psUpdate = con.prepareStatement( "UPDATE contract SET gr=? WHERE id=?" );
		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( "Автоматически после оплаты" );		
			contract_status_manager.changeStatus( status, 0 ); 	
		}
 
		// ставим в аттрибут договора дату включения
		cpu.setDateParam( cid, DATE_ON_PID, time.getTime(), 0 );
		print( "on-date: " +  TimeUtils.formatDate( time ) );
 
		// удаляем дату выключения
		cpu.deleteDateParam( cid, DATE_OFF_PID, 0 );
 
		// Закрываем в CRM задачу на обзвон должников с комментарием "Долг оплачен".
		List tasks = rtm.getNoClosedTaskList(cid);
		for( int i=0; i<tasks.size(); i++ )
		{
			RegisterTask task = (RegisterTask)tasks.get( i );
			if ( task.getGroupID()==CRM_GR && task.getTypeID()==CRM_TYPE )
			{
				print("найдена CRM-задача #"+task.getID()+". закрываем.");
				// закрываем задачу
				task.setStatus(RegisterTask.STATUS_CLOSED);
				task.setCloseTime(time.getTime());
				task.setCloseUserID(0);
				task.setComment("Долг оплачен");
				rtm.updateTask(task);
			}
		}
	}
	else
	{
		print("баланс плохой (<="+LIMIT_TO_ON.toPlainString()+"). пропускаем.");
	}
}

Для 5.0. Привязать к событиям "приход платежа" и "таймер"

--dimOn 07:34, 10 декабря 2009 (UTC)


В связи с тем, что в 5.1 событие-таймер для этих целей лучше не использовать, переделал скрипт приведенный выше, который добавляется в глобальные скрипты поведения и выполняется задачей "Выполнение глабальных скриптов по таймеру".

import java.sql.*;
import java.util.*;
import java.math.*;
 
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.tariff.*;
import bitel.billing.server.util.*;
import bitel.billing.common.KernelConst; 
import bitel.billing.server.script.bean.event.*;
 
import ru.bitel.bgbilling.plugins.crm.server.dao.*;
import ru.bitel.bgbilling.plugins.crm.common.model.*;
 
public void main( setup, con, conSlave )
{
 
// группы, для которых будет работать скрипт (номера)
int[] GROUPS ={5,6,8};
// значение порога, до которого лимит не действует (в рублях)
BigDecimal LIMITVALUE = new BigDecimal( -10 );
// ид параметра договора "Дата фиксации долга"
int DATE_OFF_PID = 22;
// ид параматра даты включения, "Дата погашения долга"
int DATE_ON_PID = 23;
//Группа "Недостаточно средств"
int GROUP_ERROR_BALANCE = 9;
// CRM - тип задачи
int CRM_TYPE = 1;
// CRM - группа решений
int CRM_GR = 1;
// если при внесении платежа баланс стал больше этой цифры, то делаем действия
BigDecimal LIMIT_TO_ON = new BigDecimal( -100 );
int[] usl ={0,2}; 
//----------
 
/**
 * Договор в одной ли из групп. Возвращается номер группы, в которой договор.
 * Или -1, если договор ни в одной из групп.
 */
int contractInGroup( Contract contract, int[] groups )
{
	for( int i=0; i<groups.length; i++ )
	{
		if( (contract.getGroups() & (1L<<groups[i])) != 0 )
		{
			return groups[i];
		}
	}
	return -1;
}
 
BalanceUtils bu = new BalanceUtils( con ); 
ContractParamUtils cpu = new ContractParamUtils( con );
ContractStatusManager contract_status_manager  = new ContractStatusManager( con );
RegisterTaskManager rtm = new RegisterTaskManager(con);
String sql = "SELECT id FROM contract";
PreparedStatement ps = con.prepareStatement( sql );
ResultSet rs = ps.executeQuery();
while(rs.next())
{
int cid = rs.getInt( 1 );
//print ("cid:"+cid);
Calendar DateNow = Calendar.getInstance();
Contract contract = new ContractManager(con).getContractByID(cid);
 
if (contract == null)
{
//	print("Dogovor ne nayden. Propuskaem");
	continue;
}
else
{
//	print("=> dogovor: "+contract.getTitle());
}
 
// проверям на вхождение в заданные группы
int cigr = contractInGroup( contract, GROUPS );
if (cigr == -1)
{
//	print("Dogovor ne vhodit v nujnie gruppi. Propuskaem.");
	continue ;
}
else
{
//	print("Dogovor vhodit v gruppu #" + cigr);
}
 
// статус получаем	
status = contract_status_manager.getStatus(cid, DateNow.getTime());
contract_status = KernelConst.CONTRACT_STATUS_ACTIVE;
if (status != null)
{
	contract_status = status.getStatus();
}
if (contract_status == null)
{
	contract_status = KernelConst.CONTRACT_STATUS_ACTIVE;
}
 
// получаем баланс
contract_balance = bu.getBalance (DateNow.getTime(), cid);
//print("Balans dogovora: "+contract_balance);
 
 
 
 
	// проверяем статус
	// Пропускаем не активные договора
	if (contract_status != KernelConst.CONTRACT_STATUS_ACTIVE) 
	{		
		print("Dogovor ne activen. Propuskaem");
		continue;
	}
 
	// берём лимит
	BigDecimal limit = contract.getBalanceLimit();
	//print("limit: "+limit);
	// может, надо поставить новый лимит?
	//limit = limit.min(LIMITVALUE);
 
 	//narabotka = bu.getSaldo (time.getTime(), cid);
   // print("Znachenie po kotoromu propuskaem: "+limit);
	// соравниваем с лимитом
	if( contract_balance.compareTo( limit )>= 0)
	{
	//	print("Баланс horoshiy");
	}
	else
	{
	//	print("Баланс plohoy");
 
		// суспендим договор
		ContractStatus status = new ContractStatus();
		status.setContractId( cid );
		status.setDateFrom( DateNow.getTime() );
		status.setDateTo( null );
		status.setStatus( KernelConst.CONTRACT_STATUS_DISCONNECTED );
		status.setComment( "Недостаточно средств" );
		contract_status_manager.changeStatus( status, 0 );
 
		// ставим в аттрибут договора дату отключения
		cpu.setDateParam( cid, DATE_OFF_PID, DateNow.getTime(), 0 );
	//	print( "off-date: " +  TimeUtils.formatDate( DateNow ) );
 
		// удаляем дату включения (если есть)
		cpu.deleteDateParam( cid, DATE_ON_PID, 0 );
 
		// заносим в группу
		contract_groups = contract.getGroups();
		contract_groups = contract_groups | 1L<<GROUP_ERROR_BALANCE;
		psUpdate = con.prepareStatement( "UPDATE contract SET gr=? WHERE id=?" );
		psUpdate.setLong( 1, contract_groups );
		psUpdate.setInt( 2, cid );
		psUpdate.executeUpdate();
 
		// Далее в CRM создаем задачу на обзвон должников (тип задачи 1),
		// группа решений (ID 3) с комментарием "Приостановлен сервером за долг".
		RegisterTask task = new RegisterTask();
		task.setComment("Приостановлен сервером за долг");
		task.setContractID(cid);
		task.setCreateTime(DateNow.getTime());
		task.setCreateUserID(0);
		task.setOpenTime(DateNow.getTime());
		task.setOpenUserID(0);
		task.setGroupID(CRM_GR);
		task.setStatus(RegisterTask.STATUS_OPEN);
		task.setTypeID(CRM_TYPE);
		rtm.updateTask(task);
	}
 
} 
 
}

--Angelwhy 11:15, 20 января 2011 (UTC)

Личные инструменты