Глобальная синхронзация услуг модуля npay с тарифным планом

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

Перейти к: навигация, поиск

Внимание! Данное решение/метод/статья относится к версии 6.0 и для других версий может быть неактуальна! Вам нужно самостоятельно поправить решение под свои нужды или воспользоваться помощью на форуме. Будем признательны, если внизу страницы или отдельной статьёй вы разместите исправленное решение для другой версии или подсказки что надо исправить.

package ru.sofit;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Vector;
 
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.sql.ConnectionSet;
import bitel.billing.common.TimeUtils;
import bitel.billing.server.contract.bean.ContractParameterManager;
import bitel.billing.server.contract.bean.ContractTariff;
import bitel.billing.server.contract.bean.ContractTariffManager;
 
/**
 * Скрипт с договора (готовый) переделан в глобальный скрипт. 
 * Синхронизирует услуги с тарифами.
 * @author dimon
 */
public class SidsSynchroGlobal
{
	public void execute( Setup setup, ConnectionSet connectionSet )
		throws Exception
	{
		System.out.println("Start");
		Connection con  = connectionSet.getConnection();
		//
		long timeStart = System.currentTimeMillis();
		Calendar now = Calendar.getInstance();
		//
		PreparedStatement ps  = con.prepareStatement( "SELECT * FROM contract ORDER BY id" );
		ResultSet rs = ps.executeQuery();
		int count = 0;
		int count_all = 0;
		while ( rs.next() )
		{
			++count_all;
			int cid = rs.getInt("id");
			String title = rs.getString("title");
			String comment = rs.getString("comment");
			System.out.println(String.format("#%s: %s (%s)", cid, title, comment));
			//
			//--------------------------------------------------------------------
			// кусок кода из старого скрипта (немного подправлен 1) с BGBS 2) чтобы брал cid не из эвента 3) отключен рекалькулятор)
			//--------------------------------------------------------------------
			//print( event ) ;
			int NPAY_MID = 4 ;
			SidsSynchroManager sidman = new SidsSynchroManager() ;
			//int cid = event.getContractId() ;
			//sidman.setDebugMode(0) ;
			sidman.setDeleteNonNeeded(1) ;
			sidman.setNpayMid(NPAY_MID) ;
			sidman.notSynchronizeServices("9,7,11");
			sidman.synchronizeServices( cid, con ) ;
			//Кусок отвечающий за перерасчет абонплаты
			// месяц за который идёт перерасчёт
			//dateTask = new GregorianCalendar();
			// набор услуг, 0- все услуги
			//serviceSet = 0;
			//Комментарий задачи
			//comment = "";
			//email = "null";
			//new RunTaskDataManager( con ).addTask( new Recalculator( NPAY_MID, dateTask, email, serviceSet, Integer.toString(cid), comment ) );
			//--------------------------------------------------------------------
			//
			++count;				
		}
		ps.close();
		System.out.println( "Total "+count_all+" contracts, processed " + count + " contracts..." );
		//
		long timeEnd = System.currentTimeMillis();
		System.out.println( "Process time: " + (timeEnd - timeStart)/1000 + " s." );
	}
 
	//--------------------------------------------------------------------
	// кусок кода из старого скрипта (немного подправлен с BGBS)
	//--------------------------------------------------------------------
 
	//Класс синхронизации услуг
	public static class SidsSynchroManager
	{
 
		public SidsSynchroManager()
		{
			vSidsData = new Vector() ;
			vNpaySidsData = new Vector() ;
			GregorianCalendar cal = new GregorianCalendar() ;
			cal.set(1970, 0, 1 ) ; 
			_DATE1_NULL = cal.getTime() ;
			cal.set(2020, 0, 1 ) ; 
			_DATE2_NULL = cal.getTime() ;
		}
 
		public void setNpayMid( int npayMid)
		{
			NPAY_MID = npayMid ;
		}
		public void setDebugMode(int debug)
		{
			_DEBUG = debug ;
		}
		//Не синхронизировать список услуг. через запятую.
		public void notSynchronizeServices( String sids ) 
		{
			noSynchroList = sids ;
		}
		public void setDeleteNonNeeded( int dnn)//0 - Не удалять не нужные сервисы, 1 - удалять
		{
			deleteNonNeeded = dnn ;
		}
		//Точка входа. Синхронизирует сервисы договора
		public void synchronizeServices( int cid, Connection con ) throws Exception
		{
			vSidsData.clear() ;
			vNpaySidsData.clear() ;
			//Выбираем глобальные тарифы, и запоминаем периоды действия их услуг
			String SQL = "SELECT tree_id, t.title, ct.date1, ct.date2 " +
	            "FROM contract_tariff AS ct LEFT JOIN tariff_plan as t ON ct.tpid=t.id " +
	            "WHERE ct.cid=" + cid ;
			//print(SQL) ;
			PreparedStatement ps = con.prepareStatement( SQL );
			ResultSet rs = ps.executeQuery();
			while ( rs.next() )
			{
				int tree_id = rs.getInt("tree_id") ;
				String title = rs.getString("title") ;
				Date date1 = rs.getDate("ct.date1") ;
				Date date2 = rs.getDate("ct.date2") ;
				if ( _DEBUG == 1 ) {
					System.out.println ("tree_id=" + tree_id + " title=" + title + " date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" 
						+ TimeUtils.format(date2, "yyyy-MM-dd") ) ;
				}
				findServicesForTariff( tree_id, 0, date1, date2, con) ;//Сохраняем услуги в набор
			}
			rs.close();
			ps.close();
			//Выбираем персональные тарифы, и запоминаем периоды действия их услуг
			SQL = "SELECT tree_id, title, date1, date2 FROM contract_tree_link WHERE cid=" + cid ;
			ps = con.prepareStatement( SQL );
			rs = ps.executeQuery();
			if ( _DEBUG == 1 ){
				System.out.println("personals") ;
			}
			while ( rs.next() )
			{
				int tree_id = rs.getInt("tree_id") ;
				String title = rs.getString("title") ;
				Date date1 = rs.getDate("date1") ;
				Date date2 = rs.getDate("date2") ;
				if( _DEBUG == 1 )	{
					System.out.println ("tree_id=" + tree_id + " title=" + title + " date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" 
						+ TimeUtils.format(date2, "yyyy-MM-dd") ) ;
				}
				findServicesForTariff( tree_id, 0, date1, date2, con ) ;
			}
			rs.close();
			ps.close();
 
 
			//Для каждой услуги синхронизируем периоды действия, отбрасывая пересекающиеся периоды
			calcActualServicePeriods( vSidsData ) ;
			//Тоже самое для услуг Абонплат.
			calcActualServicePeriods( vNpaySidsData ) ;
 
			//Выводим в вывод, список услуг, так, как они будут заведены. Здесь не могут быть пересекающихся периодов для одной услуги.
			System.out.println( "Services must be synchronized with folowing date periods") ;
			printInternalDataForContract( cid ) ;
 
			//Обновляем услуги договора
			updateSynchronizedServices( cid, 0, con )		 ;
			//Обновляем услуги абонплат договора
			updateSynchronizedServices( cid, NPAY_MID, con )		 ;
		}
 
		public void printInternalDataForContract( int cid )
		{
			System.out.println("cid="+cid) ;
			System.out.println("SERVICES:") ;
			for( int i = 0; i<vSidsData.size(); i++)
			{
				vSidsData.get(i).printData() ;
			}
			System.out.println("NPAY SERVICES:") ;
			for( int i = 0; i<vNpaySidsData.size(); i++)
			{
				vNpaySidsData.get(i).printData() ;
			}
 
		}
 
		private void updateSynchronizedServices( int cid, int nPayMid, Connection con ) throws Exception
		{
			String SQLdelNonNeeded = "" ;
			String SQLsel = "" ;
			String SQLupd = "" ;
			String SQLins = "" ;
			String SQLdel = "" ;
			Vector<SidsData> vSids = vSidsData ;
			String dateNow = TimeUtils.format(new GregorianCalendar(), "yyyy-MM-dd hh:mm:ss") ;
			if ( nPayMid == 0 ){
				SQLsel = "SELECT id, date1, date2 FROM contract_service WHERE cid=" + cid + " AND sid=? ORDER BY date1, date2" ;
				SQLupd = "UPDATE contract_service SET date1=?, date2=?, comment='Service synchronize(update from " + 
					dateNow + ")' WHERE id=?" ;
				SQLins = "INSERT INTO contract_service (cid, sid, date1, date2, comment ) VALUES ( " + 
					cid + ", ? , ? , ?, 'Service 	synchronize(insert from " + dateNow + ")')" ;
				SQLdel = "DELETE FROM contract_service WHERE id=?" ;			
				String sidslist = getServiceList(vSidsData) ;
				if ( sidslist == "" ) { sidslist = "-1" ;}
				SQLdelNonNeeded = "DELETE FROM contract_service WHERE cid=" + cid + " AND sid NOT IN (" + 
					sidslist +") AND sid NOT IN (" + noSynchroList + ")" ;
			}
			else{
				vSids = vNpaySidsData ;
				SQLsel = "SELECT id, date1, date2 FROM npay_service_object_" + nPayMid + " WHERE cid=" + cid + " AND sid=? ORDER BY date1, date2" ;
				SQLupd = "UPDATE npay_service_object_" + nPayMid + " SET date1=?, date2=?, comment='Service synchronize(update from " + 
					dateNow + ")' WHERE id=?" ;
				SQLins = "INSERT INTO npay_service_object_" + nPayMid + " (cid, sid, date1, date2, comment ) VALUES ( " + 
					cid + ", ? , ? , ?, 'Service 	synchronize(insert from " + dateNow + ")')" ;
				SQLdel = "DELETE FROM npay_service_object_" + nPayMid + " WHERE id=?" ;			
				String sidslist = getServiceList(vNpaySidsData) ;
				if ( sidslist == "" ) {
					 sidslist = "-1" ;
				} else { //Список услуг абонплат для синхронизации не пуст. Добавляем в таблицу contract_module запись при необходимости
					String SQLtmp = "SELECT mid FROM contract_module WHERE cid=" + cid + " AND mid=" + NPAY_MID ;
					PreparedStatement ps = con.prepareStatement( SQLtmp );
					ResultSet rs = ps.executeQuery() ;
					if( !rs.next() )
					{
						SQLtmp = "INSERT INTO contract_module (cid,mid) VALUES (" + cid + "," + NPAY_MID + ")" ;
						ps = con.prepareStatement( SQLtmp );
						ps.executeUpdate() ;
					}
					rs.close();
					ps.close();
				}
 
				SQLdelNonNeeded = "DELETE FROM npay_service_object_" + nPayMid + " WHERE cid=" + cid + " AND sid NOT IN (" + sidslist + ") AND sid NOT IN (" + noSynchroList + ")" ;
			}
 
 
 
			if ( deleteNonNeeded == 1 )
			{
 
				System.out.println( SQLdelNonNeeded ) ;
				PreparedStatement psDelOther = con.prepareStatement( SQLdelNonNeeded ) ;
				psDelOther.executeUpdate( SQLdelNonNeeded ) ;
			}
			PreparedStatement ps = con.prepareStatement( SQLsel );
			PreparedStatement psUpd = con.prepareStatement( SQLupd );
			PreparedStatement psIns = con.prepareStatement( SQLins );
			PreparedStatement psDel = con.prepareStatement( SQLdel );
 
			ResultSet rs ;
			SidsData sd ;
			Date date1 = null, date2 = null ;
			for( int i = 0; i<vSids.size(); i++)
			{
				sd = vSids.get(i) ;
				int sid = sd.sid ;
				ps.setInt(1, sid) ;
				rs = ps.executeQuery() ;
				int j = 0 ; 
				while( rs.next() )
				{
					int id = rs.getInt("id") ;
					date1 = rs.getDate("date1") ;
					date2 = rs.getDate("date2") ;
					//Чтобы при сравнении дат equals не давал exeption, подменяем значения null
					//print( "date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ;
					if ( date1 == null ){
						date1 = (Date) _DATE1_NULL.clone() ;
					}
					if ( date2 == null ){
						date2 = (Date) _DATE2_NULL.clone() ;
					}
					//Лишняя услуга, удаляем
					if ( j >= sd.vDate1.size() )
					{
						psDel.setInt( 1, id ) ;
						psDel.executeUpdate() ;
						if (_DEBUG==1){
							System.out.println( "Delete service with id=" + id + " for service="+sid + 
						" date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ;
							System.out.println( "psDel=" + psDel ) ;
						}
						continue ;
					}
 
 
					if ( !date1.equals(sd.vDate1.get(j)) || !date2.equals(sd.vDate2.get(j)) )
					{
						//Возвращаем значения null при необходимости  для обновления инфы в БД
						if ( sd.vDate1.get(j).equals( _DATE1_NULL) ){
							sd.vDate1.set( j, null ) ;
						}
						if ( sd.vDate2.get(j).equals( _DATE2_NULL) ){
							sd.vDate2.set( j, null ) ;
						}
						psUpd.setInt( 3, id ) ;
						psUpd.setDate( 1, TimeUtils.convertDateToSqlDate(sd.vDate1.get(j)) ) ;
						psUpd.setDate( 2, TimeUtils.convertDateToSqlDate(sd.vDate2.get(j)) ) ;
						psUpd.executeUpdate() ;
						if (_DEBUG==1){
							System.out.println( "Update service with id=" + id + " for service="+sid + " previous date1=" + 
							TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ;
							System.out.println( "psUpd=" + psUpd ) ;
						}
					}
					j++ ;
				}//end while
 
				for( ; j < sd.vDate1.size(); j++)
				{
					if ( sd.vDate1.get(j).equals( _DATE1_NULL) ){
						sd.vDate1.set( j, null ) ;
					}
					if ( sd.vDate2.get(j).equals( _DATE2_NULL) ){
						sd.vDate2.set( j, null ) ;
					}
					psIns.setInt(1, sid ) ;
					psIns.setDate( 2, TimeUtils.convertDateToSqlDate(sd.vDate1.get(j)) ) ;
					psIns.setDate( 3, TimeUtils.convertDateToSqlDate(sd.vDate2.get(j)) ) ;
					if (_DEBUG==1){
						System.out.println( "Insert new service="+sid + " date1=" + 
						TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ;
						System.out.println( "psIns" + psIns ) ;
					}
					psIns.executeUpdate() ;
				}
 
			}
 
		}
 
		private String getServiceList(Vector<SidsData> vSids)
		{
			String sids = "";
			int i ;
			for( i = 0; i<vSids.size()-1; i++)
			{
				sids += "" + vSids.get(i).sid + "," ;
			}
			if ( i < vSids.size()) {
				sids += "" + vSids.get(i).sid ;
			}
			return sids ;
		}
 
		private void calcActualServicePeriods( Vector<SidsData> vSids )
		{
			prepareInternalData() ;
			SidsData sd ;
			Vector<Date> vDate1 = new Vector<Date>() ;
			Vector<Date> vDate2 = new Vector<Date>() ;
			Date date1 ;
			Date date2 ;
			GregorianCalendar date1cal = new GregorianCalendar() ; //Для хранения date1+1 день
			int k = 0 ;
			for( int i = 0; i<vSids.size(); i++)
			{
				sd = vSids.get(i) ;
				vDate1.clear() ;
				vDate2.clear() ;
				for ( int j = 0 ; j < sd.vDate1.size() ;  )//Отсеиваем ненужные периоды
				{
					date1 = sd.vDate1.get(j) ;
					date2 = sd.vDate2.get(j) ;
					if ( date1.compareTo( date2) > 0 )
					{
						System.out.println("Fatal error,  date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " > date2=" 
						+ TimeUtils.format(date2, "yyyy-MM-dd") ) ;
						System.out.println("Services was not synchronized...") ;
						return ;
					}
					for( j++ ; j<sd.vDate1.size(); j++)
					{
						date1cal.setTime( sd.vDate1.get(j) ) ;
						date1cal.roll(Calendar.DAY_OF_YEAR,-1) ;
						if ( date2.compareTo(date1cal.getTime()) < 0 ) // Нашли нужный date2 для date1 ;
						{
							break ;
						}
						else
						{
							date2 = sd.vDate2.get(j) ;
						}
					}
					vDate1.add(date1) ;
					vDate2.add(date2) ;
				}
 
				sd.vDate1.clear() ;
				sd.vDate2.clear() ;
				sd.vDate1 = (Vector<Date>) vDate1.clone() ;
				sd.vDate2 = (Vector<Date>) vDate2.clone() ;
 
			}
		}
 
		private void prepareInternalData()//Подготовливает внутренние данные для основного алгоритма. Сортирует массивы date услуг
		{
			SidsData sd ;
			for( int i = 0; i<vSidsData.size(); i++)
			{
				sd = vSidsData.get(i) ;
				Collections.sort(sd.vDate1 ) ;
				Collections.sort(sd.vDate2 ) ;
			}
			for( int i = 0; i<vNpaySidsData.size(); i++)
			{
				sd = vNpaySidsData.get(i) ;
				Collections.sort(sd.vDate1 ) ;
				Collections.sort(sd.vDate2 ) ;
 
			}
 
		}
 
		private void addSid( int sid, Date date1, Date date2, int npayService )
		{
			String[] noSids = noSynchroList.split(",") ;
			for ( int  i = 0 ; i<noSids.length; i++ )
			{
				if ( Integer.parseInt( noSids[i].trim() ) == sid ) { return ;}
			}
			//Заменяем нулевые значения дат значениями _DATE1_NULL и DATE2_NULL соответсвенно
			if ( date1 == null ) {
				date1 = (Date) _DATE1_NULL.clone() ;
			}
			if ( date2 == null ) {
				date2 = (Date) _DATE2_NULL.clone() ;
			}
 
			Vector<SidsData> vSids = vSidsData;
			if ( npayService != 0 )
			{
				vSids = vNpaySidsData ;
			}
			int f = 0 ;
			SidsData sd ;
			for ( int i=0; i < vSids.size(); i++ )
			{
				sd = vSids.get(i) ;
				if (sd.sid == sid)
				{
					sd.vDate1.add(date1) ;
					sd.vDate2.add(date2) ;
					f = 1 ; break ;
				}
			}
			if ( f == 0 )
			{
				sd = new SidsData( sid ) ;
				sd.vDate1.add(date1) ;
				sd.vDate2.add(date2) ;
				vSids.add( sd ) ;
			}
		}
 
		private	void findServicesForTariff( int tree_id, int mid /*если не 0, то выборка из родительского тарифа*/, 
	 		Date date1, Date date2, Connection con) throws Exception 
		{
			String SQL = "SELECT id, mid, parent_tree FROM module_tariff_tree WHERE tree_id=" + tree_id ;
			if ( mid != 0 )
			{
				SQL += " AND mid=" + mid ;
			}
			//print(SQL) ;
			PreparedStatement ps = con.prepareStatement( SQL );
			ResultSet rs = ps.executeQuery() ;
 
			while ( rs.next() )
			{
				int mtreeid = rs.getInt("id") ;
				int _mid = rs.getInt("mid") ;
				int parent_tree = rs.getInt("parent_tree") ;
				if (parent_tree != 0 )
				{
					findServicesForTariff( parent_tree, _mid, date1, date2, con ) ;
					continue ;
				}
				findServicesForTariff2( mtreeid, _mid, date1, date2, con ) ;
			}
			rs.close();
			ps.close();
		}
 
		private void findServicesForTariff2( int mtreeid, int mid, Date date1, Date date2, Connection con ) throws Exception
		{
			String SQL = "SELECT type, data " + 
				"FROM mtree_node " +
				"WHERE mtree_id=" + mtreeid + " AND type IN ('service', 'multi_service', 'month_mode', 'day_mode')" ;
			PreparedStatement ps = con.prepareStatement( SQL ) ;
			ResultSet rs = ps.executeQuery() ;
			int sid = 0;
			while ( rs.next() )
			{
				String type = rs.getString("type") ;
				String data = rs.getString("data") ;
				//print ( "type=" + type + " data=" + data) ;
				if (type.equals("service") )
				{
					sid = Integer.parseInt( data ) ;
					addSid( sid, date1, date2, 0 ) ; //Добавляем найденную услугу в набор найденных услуг
 
					//print ( "sid=" + sid ) ;
				}
				else if( type.equals("multi_service") )
				{
					String[] ss = data.split("&") ;
					String[] sids = ss[1].split(",") ;
					//print ( "sids=" + ss[1] ) ;
					for ( int i=0; i < sids.length; i++ )
					{
						sid=Integer.parseInt(sids[i]) ;
						addSid( sid, date1, date2, 0 ) ; //Добавляем найденную услугу в набор найденных услуг
						//print( "sid = " + sid ) ;
					}
				}
				else if( type.equals("month_mode") )
				{
					String[] ss = data.split("%") ;
					for ( int i = 0; i < ss.length ; i++ )
					{
						String[] sids=ss[i].split("&") ;
						if ( sids[0].equals("sid") )
						{
							sid = Integer.parseInt(sids[1]) ;
							addSid( sid, date1, date2, 1 ) ; //Добавляем найденную услугу в набор найденных услуг
							break ;
						}
					}
					//print( "month_mode sid = " + sid ) ;
				}
				else if( type.equals("day_mode") )
				{
					String[] ss = data.split("%") ;
					for ( int i = 0; i < ss.length ; i++ )
					{
						String[] sids=ss[i].split("&") ;
						if ( sids[0].equals("sid") )
						{
							sid = Integer.parseInt(sids[1]) ;
							addSid( sid, date1, date2, 1 ) ; //Добавляем найденную услугу в набор найденных услуг
							break ;
						}
					}
					//print( "day_mode sid = " + sid ) ;
				}
 
			}//end while
			rs.close();
			ps.close();
		}
 
 
		//внутренниц класс для хранения услуги и множества дат date1 и date2 
		private	static class SidsData
		{
			public int sid ;
			public Vector<Date> vDate1 ;
			public Vector<Date> vDate2 ;
 
			public SidsData()
			{
				sid = 0 ;
				vDate1 = new Vector<Date>() ;
				vDate2 = new Vector<Date>() ;
			}
 
			public SidsData( int s )
			{
				sid=s ;
				vDate1 = new Vector<Date>() ;
				vDate2 = new Vector<Date>() ;
			}
			public void printData()
			{
				System.out.println ("sid=" + sid) ;
				for( int i=0; i<vDate1.size(); i++ )
				{
					Date date1 = vDate1.get(i) ;
					Date date2 = vDate2.get(i) ;
					if ( date1.equals( _DATE1_NULL) ){
						date1 = null ;
					}
					if ( date2.equals( _DATE2_NULL) ){
						date2 = null ;
					}
 
					System.out.println (" date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" 
						+ TimeUtils.format(date2, "yyyy-MM-dd") ) ;				
				}
			}
		}
 
		private int NPAY_MID=4 ;
		private int _DEBUG=0 ;
		private int deleteNonNeeded = 0 ;
		static private Date _DATE1_NULL ;
		static private Date _DATE2_NULL ;
		private Vector<SidsData> vSidsData ;
		private Vector<SidsData> vNpaySidsData ;
		private String noSynchroList = "1000000" ;//не синхронизировать услуги.
	}
}
 < /source>
Личные инструменты