Синхронизация услуг договора в соответствии с тарифными планами
Материал из BiTel WiKi
Skyb (Обсуждение | вклад) |
Skyb (Обсуждение | вклад) |
||
Строка 629: | Строка 629: | ||
"ct.date1, ct.date2 FROM contract_tariff AS ct LEFT JOIN tariff_tree_link as ttl ON ct.tpid=ttl.tpid " + | "ct.date1, ct.date2 FROM contract_tariff AS ct LEFT JOIN tariff_tree_link as ttl ON ct.tpid=ttl.tpid " + | ||
"WHERE ct.cid=" + cid ; | "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 ) { | ||
+ | print ("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) ;//Сохраняем услуги в набор | ||
+ | } | ||
+ | //Выбираем персональные тарифы, и запоминаем периоды действия их услуг | ||
+ | SQL = "SELECT tree_id, title, date1, date2 FROM contract_tree_link WHERE cid=" + cid ; | ||
+ | ps = con.prepareStatement( SQL ); | ||
+ | rs = ps.executeQuery(); | ||
+ | if ( _DEBUG == 1 ){ | ||
+ | print("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 ) { | ||
+ | print ("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 ) ; | ||
+ | } | ||
+ | |||
+ | |||
+ | //Для каждой услуги синхронизируем периоды действия, отбрасывая пересекающиеся периоды | ||
+ | calcActualServicePeriods( vSidsData ) ; | ||
+ | //Тоже самое для услуг Абонплат. | ||
+ | calcActualServicePeriods( vNpaySidsData ) ; | ||
+ | |||
+ | //Выводим в вывод, список услуг, так, как они будут заведены. Здесь не могут быть пересекающихся периодов для одной услуги. | ||
+ | print( "Services must be synchronized with folowing date periods") ; | ||
+ | printInternalDataForContract( cid ) ; | ||
+ | |||
+ | //Обновляем услуги договора | ||
+ | updateSynchronizedServices( cid, 0, con ) ; | ||
+ | //Обновляем услуги абонплат договора | ||
+ | updateSynchronizedServices( cid, NPAY_MID, con ) ; | ||
+ | } | ||
+ | |||
+ | public void printInternalDataForContract( int cid ) | ||
+ | { | ||
+ | print("cid="+cid) ; | ||
+ | print("SERVICES:") ; | ||
+ | for( int i = 0; i<vSidsData.size(); i++) | ||
+ | { | ||
+ | vSidsData.get(i).printData() ; | ||
+ | } | ||
+ | print("NPAY SERVICES:") ; | ||
+ | for( int i = 0; i<vNpaySidsData.size(); i++) | ||
+ | { | ||
+ | vNpaySidsData.get(i).printData() ; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | private void updateSynchronizedServices( int cid, int nPayMid, Connection con ) | ||
+ | { | ||
+ | String SQLdelNonNeeded = "" ; | ||
+ | String SQLsel = "" ; | ||
+ | String SQLupd = "" ; | ||
+ | String SQLins = "" ; | ||
+ | String SQLdel = "" ; | ||
+ | Vector 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 запись при необходимости | ||
+ | SQLtmp = "SELECT mid FROM contract_module WHERE cid=" + cid + " AND mid=" + NPAY_MID ; | ||
+ | PreparedStatement ps = con.prepareStatement( SQLtmp ); | ||
+ | rs = ps.executeQuery() ; | ||
+ | if( !rs.next() ) | ||
+ | { | ||
+ | SQLtmp = "INSERT INTO contract_module (cid,mid) VALUES (" + cid + "," + NPAY_MID + ")" ; | ||
+ | ps = con.prepareStatement( SQLtmp ); | ||
+ | ps.executeUpdate() ; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | SQLdelNonNeeded = "DELETE FROM npay_service_object_" + nPayMid + " WHERE cid=" + cid + " AND sid NOT IN (" + sidslist + ") AND sid NOT IN (" + noSynchroList + ")" ; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | if ( deleteNonNeeded == 1 ) | ||
+ | { | ||
+ | |||
+ | print( 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, date2 ; | ||
+ | for( int i = 0; i<vSids.size(); i++) | ||
+ | { | ||
+ | sd = vSids.get(i) ; | ||
+ | int sid = sd.sid ; | ||
+ | ps.setInt(1, sid) ; | ||
+ | rs = ps.executeQuery() ; | ||
+ | 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 = _DATE1_NULL.clone() ; | ||
+ | } | ||
+ | if ( date2 == null ){ | ||
+ | date2 = _DATE2_NULL.clone() ; | ||
+ | } | ||
+ | //Лишняя услуга, удаляем | ||
+ | if ( j >= sd.vDate1.size() ) | ||
+ | { | ||
+ | psDel.setInt( 1, id ) ; | ||
+ | psDel.executeUpdate() ; | ||
+ | if (_DEBUG==1){ | ||
+ | print( "Delete service with id=" + id + " for service="+sid + | ||
+ | " date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; | ||
+ | print( "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, sd.vDate1.get(j) ) ; | ||
+ | psUpd.setDate( 2, sd.vDate2.get(j) ) ; | ||
+ | psUpd.executeUpdate() ; | ||
+ | if (_DEBUG==1){ | ||
+ | print( "Update service with id=" + id + " for service="+sid + " previous date1=" + | ||
+ | TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; | ||
+ | print( "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, sd.vDate1.get(j) ) ; | ||
+ | psIns.setDate( 3, sd.vDate2.get(j) ) ; | ||
+ | if (_DEBUG==1){ | ||
+ | print( "Insert new service="+sid + " date1=" + | ||
+ | TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; | ||
+ | print( "psIns" + psIns ) ; | ||
+ | } | ||
+ | psIns.executeUpdate() ; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | private String getServiceList(Vector 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 calcActualServicePeriods( Vector vSids ) | ||
+ | { | ||
+ | prepareInternalData() ; | ||
+ | SidsData sd ; | ||
+ | Vector vDate1 = new Vector() ; | ||
+ | Vector vDate2 = new Vector() ; | ||
+ | Date date1 ; | ||
+ | Date date2 ; | ||
+ | GregorianCalendar date1cal = new GregorianCalendar() ; //Для хранения date1+1 день | ||
+ | k = 0 ; | ||
+ | for( int i = 0; i<vSids.size(); i++) | ||
+ | { | ||
+ | sd = vSids.get(i) ; | ||
+ | vDate1.clear() ; | ||
+ | vDate2.clear() ; | ||
+ | for ( j = 0 ; j < sd.vDate1.size() ; )//Отсеиваем ненужные периоды | ||
+ | { | ||
+ | date1 = sd.vDate1.get(j) ; | ||
+ | date2 = sd.vDate2.get(j) ; | ||
+ | if ( date1.compareTo( date2) > 0 ) | ||
+ | { | ||
+ | print("Fatal error, date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " > date2=" | ||
+ | + TimeUtils.format(date2, "yyyy-MM-dd") ) ; | ||
+ | print("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 = vDate1.clone() ; | ||
+ | sd.vDate2 = vDate2.clone() ; | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | private 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 = _DATE1_NULL.clone() ; | ||
+ | } | ||
+ | if ( date2 == null ) { | ||
+ | date2 = _DATE2_NULL.clone() ; | ||
+ | } | ||
+ | |||
+ | Vector 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) | ||
+ | { | ||
+ | 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 ) ; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | private void findServicesForTariff2( int mtreeid, int mid, Date date1, Date date2, Connection con ) | ||
+ | { | ||
+ | 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 | ||
+ | } | ||
+ | |||
+ | |||
+ | //внутренниц класс для хранения услуги и множества дат date1 и date2 | ||
+ | private class SidsData{ | ||
+ | public int sid ; | ||
+ | public Vector vDate1 ; | ||
+ | public Vector vDate2 ; | ||
+ | |||
+ | public SidsData() | ||
+ | { | ||
+ | sid = 0 ; | ||
+ | vDate1 = new Vector() ; | ||
+ | vDate2 = new Vector() ; | ||
+ | } | ||
+ | |||
+ | public SidsData( int s ) | ||
+ | { | ||
+ | sid=s ; | ||
+ | vDate1 = new Vector() ; | ||
+ | vDate2 = new Vector() ; | ||
+ | } | ||
+ | public printData() | ||
+ | { | ||
+ | print ("sid=" + sid) ; | ||
+ | for( 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 ; | ||
+ | } | ||
+ | |||
+ | print (" 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 vSidsData ; | ||
+ | private Vector vNpaySidsData ; | ||
+ | private String noSynchroList = "1000000" ;//не синхронизировать услуги. | ||
+ | } | ||
+ | </source> | ||
+ | Пофиксено для 5.2 | ||
+ | |||
+ | <source lang="java"> | ||
+ | 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.npay.bean.*; | ||
+ | import bitel.billing.server.script.bean.event.*; | ||
+ | import bitel.billing.server.npay.*; | ||
+ | |||
+ | |||
+ | public void onEvent( event, setup, con, conSlave ) | ||
+ | { | ||
+ | //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 ) ; | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | //Класс синхронизации услуг | ||
+ | public 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 ) | ||
+ | { | ||
+ | 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) ; | //print(SQL) ; | ||
PreparedStatement ps = con.prepareStatement( SQL ); | PreparedStatement ps = con.prepareStatement( SQL ); |
Версия 06:01, 14 февраля 2012
Скрипт добавляет/изменяет услуги и синхронизирует периоды действия услуг автоматически в соответствии с услугами используемыми в тарифных планах договора. Его можно повесить на событие Изменение/удаление тарифного плана, и не задумываться, какие услуги используется в тарифах. Алгоритм коротко таков: Скрипт находит все услуги используемые во всех тарифных планах договора, и запоминает их периоды действия, получаем наборы
sid1 date1_tariff1_with_sid1 date2_tariff_with_sid1 ... date1_tariffN_with_sid1 date2_tariffN_with_sid1 ... sidN date1_tariff1_with_sidN date2_tariff_with_sidN ... date1_tariffN_with_sidN date2_tariffN_with_sidN
из этих наборов периодов отбрасываем пересекающиеся, и в соответсвии с результатом обновляем существующие услуги договора. Удобно!
upd 14.04.2010 Добавлен метод notSynchronizeServices(sids) ; в котором указывается список услуг, через запятую, которую не надо синхронизровать. Добавлено добавление записи(в случае необходимости) для договора, в таблицу contract_module для модуля NPay (если имеются услуги NPay, которые нужно синхронизировать). Добавлено по причине того что, на момент написания скрипта, при отсутствии записи в contract_module для NPay абонплата списывалась в полном объеме без учета статусов.
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.npay.bean.*; import bitel.billing.server.script.bean.event.*; import bitel.billing.server.npay.*; public void onEvent( event, setup, con, conSlave ) { //print( event ) ; int NPAY_MID = 8 ; SidsSynchroManager sidman = new SidsSynchroManager() ; int cid = event.getContractID() ; //sidman.setDebugMode(0) ; sidman.notSynchronizeServices("11,21,41,42,44");//Указываем список сервисов, которые не хотим, чтобы синхронизировались sidman.setDeleteNonNeeded(1) ;//Удаляем не нужные сервисы из договора, за исключением сервисов, которые не синхронизируем. sidman.setNpayMid(NPAY_MID) ;//Указываем ИД модуля абонплат sidman.synchronizeServices( cid, con ) ; } //Класс синхронизации услуг public 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 ) { vSidsData.clear() ; vNpaySidsData.clear() ; //Выбираем глобальные тарифы, и запоминаем периоды действия их услуг String SQL = "SELECT tree_id, (SELECT t.title FROM tariff_plan AS t WHERE t.id=ct.tpid) as title," + "ct.date1, ct.date2 FROM contract_tariff AS ct LEFT JOIN tariff_tree_link as ttl ON ct.tpid=ttl.tpid " + "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 ) { print ("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) ;//Сохраняем услуги в набор } //Выбираем персональные тарифы, и запоминаем периоды действия их услуг SQL = "SELECT tree_id, title, date1, date2 FROM contract_tree_link WHERE cid=" + cid ; ps = con.prepareStatement( SQL ); rs = ps.executeQuery(); if ( _DEBUG == 1 ){ print("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 ) { print ("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 ) ; } //Для каждой услуги синхронизируем периоды действия, отбрасывая пересекающиеся периоды calcActualServicePeriods( vSidsData ) ; //Тоже самое для услуг Абонплат. calcActualServicePeriods( vNpaySidsData ) ; //Выводим в вывод, список услуг, так, как они будут заведены. Здесь не могут быть пересекающихся периодов для одной услуги. print( "Services must be synchronized with folowing date periods") ; printInternalDataForContract( cid ) ; //Обновляем услуги договора updateSynchronizedServices( cid, 0, con ) ; //Обновляем услуги абонплат договора updateSynchronizedServices( cid, NPAY_MID, con ) ; } public void printInternalDataForContract( int cid ) { print("cid="+cid) ; print("SERVICES:") ; for( int i = 0; i<vSidsData.size(); i++) { vSidsData.get(i).printData() ; } print("NPAY SERVICES:") ; for( int i = 0; i<vNpaySidsData.size(); i++) { vNpaySidsData.get(i).printData() ; } } private void updateSynchronizedServices( int cid, int nPayMid, Connection con ) { Vector 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 запись при необходимости SQLtmp = "SELECT mid FROM contract_module WHERE cid=" + cid + " AND mid=" + NPAY_MID ; PreparedStatement ps = con.prepareStatement( SQLtmp ); rs = ps.executeQuery() ; if( !rs.next() ) { SQLtmp = "INSERT INTO contract_module (cid,mid) VALUES (" + cid + "," + NPAY_MID + ")" ; ps = con.prepareStatement( SQLtmp ); ps.executeUpdate() ; } } SQLdelNonNeeded = "DELETE FROM npay_service_object_" + nPayMid + " WHERE cid=" + cid + " AND sid NOT IN (" + sidslist + ") AND sid NOT IN (" + noSynchroList + ")" ; } if ( deleteNonNeeded == 1 ) { print( 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, date2 ; for( int i = 0; i<vSids.size(); i++) { sd = vSids.get(i) ; int sid = sd.sid ; ps.setInt(1, sid) ; rs = ps.executeQuery() ; 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 = _DATE1_NULL.clone() ; } if ( date2 == null ){ date2 = _DATE2_NULL.clone() ; } //Лишняя услуга, удаляем if ( j >= sd.vDate1.size() ) { psDel.setInt( 1, id ) ; psDel.executeUpdate() ; if (_DEBUG==1){ print( "Delete service with id=" + id + " for service="+sid + " date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; print( "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, sd.vDate1.get(j) ) ; psUpd.setDate( 2, sd.vDate2.get(j) ) ; psUpd.executeUpdate() ; if (_DEBUG==1){ print( "Update service with id=" + id + " for service="+sid + " previous date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; print( "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, sd.vDate1.get(j) ) ; psIns.setDate( 3, sd.vDate2.get(j) ) ; if (_DEBUG==1){ print( "Insert new service="+sid + " date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; print( "psIns" + psIns ) ; } psIns.executeUpdate() ; } } } private String getServiceList(Vector 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 calcActualServicePeriods( Vector vSids ) { prepareInternalData() ; SidsData sd ; Vector vDate1 = new Vector() ; Vector vDate2 = new Vector() ; Date date1 ; Date date2 ; GregorianCalendar date1cal = new GregorianCalendar() ; //Для хранения date1+1 день k = 0 ; for( int i = 0; i<vSids.size(); i++) { sd = vSids.get(i) ; vDate1.clear() ; vDate2.clear() ; for ( j = 0 ; j < sd.vDate1.size() ; )//Отсеиваем ненужные периоды { date1 = sd.vDate1.get(j) ; date2 = sd.vDate2.get(j) ; if ( date1.compareTo( date2) > 0 ) { print("Fatal error, date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " > date2=" + TimeUtils.format(date2, "yyyy-MM-dd") ) ; print("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 = vDate1.clone() ; sd.vDate2 = vDate2.clone() ; } } private 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 = _DATE1_NULL.clone() ; } if ( date2 == null ) { date2 = _DATE2_NULL.clone() ; } Vector 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) { 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 ) ; } } private void findServicesForTariff2( int mtreeid, int mid, Date date1, Date date2, Connection con ) { 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 } //внутренниц класс для хранения услуги и множества дат date1 и date2 private class SidsData{ public int sid ; public Vector vDate1 ; public Vector vDate2 ; public SidsData() { sid = 0 ; vDate1 = new Vector() ; vDate2 = new Vector() ; } public SidsData( int s ) { sid=s ; vDate1 = new Vector() ; vDate2 = new Vector() ; } public printData() { print ("sid=" + sid) ; for( 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 ; } print (" date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd") ) ; } } } private int NPAY_MID=8 ; private int _DEBUG=0 ; private int deleteNonNeeded = 0 ; static private Date _DATE1_NULL ; static private Date _DATE2_NULL ; private Vector vSidsData ; private Vector vNpaySidsData ; private String noSynchroList = "1000000" ;//не синхронизировать услуги. }
Пофиксино для версии 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.npay.bean.*; import bitel.billing.server.script.bean.event.*; import bitel.billing.server.npay.*; public void onEvent( event, setup, con, conSlave ) { //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 ) ; } //Класс синхронизации услуг public 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 ) { vSidsData.clear() ; vNpaySidsData.clear() ; //Выбираем глобальные тарифы, и запоминаем периоды действия их услуг String SQL = "SELECT tree_id, (SELECT t.title FROM tariff_plan AS t WHERE t.id=ct.tpid) as title," + "ct.date1, ct.date2 FROM contract_tariff AS ct LEFT JOIN tariff_tree_link as ttl ON ct.tpid=ttl.tpid " + "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 ) { print ("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) ;//Сохраняем услуги в набор } //Выбираем персональные тарифы, и запоминаем периоды действия их услуг SQL = "SELECT tree_id, title, date1, date2 FROM contract_tree_link WHERE cid=" + cid ; ps = con.prepareStatement( SQL ); rs = ps.executeQuery(); if ( _DEBUG == 1 ){ print("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 ) { print ("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 ) ; } //Для каждой услуги синхронизируем периоды действия, отбрасывая пересекающиеся периоды calcActualServicePeriods( vSidsData ) ; //Тоже самое для услуг Абонплат. calcActualServicePeriods( vNpaySidsData ) ; //Выводим в вывод, список услуг, так, как они будут заведены. Здесь не могут быть пересекающихся периодов для одной услуги. print( "Services must be synchronized with folowing date periods") ; printInternalDataForContract( cid ) ; //Обновляем услуги договора updateSynchronizedServices( cid, 0, con ) ; //Обновляем услуги абонплат договора updateSynchronizedServices( cid, NPAY_MID, con ) ; } public void printInternalDataForContract( int cid ) { print("cid="+cid) ; print("SERVICES:") ; for( int i = 0; i<vSidsData.size(); i++) { vSidsData.get(i).printData() ; } print("NPAY SERVICES:") ; for( int i = 0; i<vNpaySidsData.size(); i++) { vNpaySidsData.get(i).printData() ; } } private void updateSynchronizedServices( int cid, int nPayMid, Connection con ) { String SQLdelNonNeeded = "" ; String SQLsel = "" ; String SQLupd = "" ; String SQLins = "" ; String SQLdel = "" ; Vector 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 запись при необходимости SQLtmp = "SELECT mid FROM contract_module WHERE cid=" + cid + " AND mid=" + NPAY_MID ; PreparedStatement ps = con.prepareStatement( SQLtmp ); rs = ps.executeQuery() ; if( !rs.next() ) { SQLtmp = "INSERT INTO contract_module (cid,mid) VALUES (" + cid + "," + NPAY_MID + ")" ; ps = con.prepareStatement( SQLtmp ); ps.executeUpdate() ; } } SQLdelNonNeeded = "DELETE FROM npay_service_object_" + nPayMid + " WHERE cid=" + cid + " AND sid NOT IN (" + sidslist + ") AND sid NOT IN (" + noSynchroList + ")" ; } if ( deleteNonNeeded == 1 ) { print( 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, date2 ; for( int i = 0; i<vSids.size(); i++) { sd = vSids.get(i) ; int sid = sd.sid ; ps.setInt(1, sid) ; rs = ps.executeQuery() ; 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 = _DATE1_NULL.clone() ; } if ( date2 == null ){ date2 = _DATE2_NULL.clone() ; } //Лишняя услуга, удаляем if ( j >= sd.vDate1.size() ) { psDel.setInt( 1, id ) ; psDel.executeUpdate() ; if (_DEBUG==1){ print( "Delete service with id=" + id + " for service="+sid + " date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; print( "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, sd.vDate1.get(j) ) ; psUpd.setDate( 2, sd.vDate2.get(j) ) ; psUpd.executeUpdate() ; if (_DEBUG==1){ print( "Update service with id=" + id + " for service="+sid + " previous date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; print( "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, sd.vDate1.get(j) ) ; psIns.setDate( 3, sd.vDate2.get(j) ) ; if (_DEBUG==1){ print( "Insert new service="+sid + " date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; print( "psIns" + psIns ) ; } psIns.executeUpdate() ; } } } private String getServiceList(Vector 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 calcActualServicePeriods( Vector vSids ) { prepareInternalData() ; SidsData sd ; Vector vDate1 = new Vector() ; Vector vDate2 = new Vector() ; Date date1 ; Date date2 ; GregorianCalendar date1cal = new GregorianCalendar() ; //Для хранения date1+1 день k = 0 ; for( int i = 0; i<vSids.size(); i++) { sd = vSids.get(i) ; vDate1.clear() ; vDate2.clear() ; for ( j = 0 ; j < sd.vDate1.size() ; )//Отсеиваем ненужные периоды { date1 = sd.vDate1.get(j) ; date2 = sd.vDate2.get(j) ; if ( date1.compareTo( date2) > 0 ) { print("Fatal error, date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " > date2=" + TimeUtils.format(date2, "yyyy-MM-dd") ) ; print("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 = vDate1.clone() ; sd.vDate2 = vDate2.clone() ; } } private 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 = _DATE1_NULL.clone() ; } if ( date2 == null ) { date2 = _DATE2_NULL.clone() ; } Vector 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) { 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 ) ; } } private void findServicesForTariff2( int mtreeid, int mid, Date date1, Date date2, Connection con ) { 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 } //внутренниц класс для хранения услуги и множества дат date1 и date2 private class SidsData{ public int sid ; public Vector vDate1 ; public Vector vDate2 ; public SidsData() { sid = 0 ; vDate1 = new Vector() ; vDate2 = new Vector() ; } public SidsData( int s ) { sid=s ; vDate1 = new Vector() ; vDate2 = new Vector() ; } public printData() { print ("sid=" + sid) ; for( 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 ; } print (" 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 vSidsData ; private Vector vNpaySidsData ; private String noSynchroList = "1000000" ;//не синхронизировать услуги. }
Пофиксено для 5.2
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.npay.bean.*; import bitel.billing.server.script.bean.event.*; import bitel.billing.server.npay.*; public void onEvent( event, setup, con, conSlave ) { //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 ) ; } //Класс синхронизации услуг public 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 ) { 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 ) { print ("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) ;//Сохраняем услуги в набор } //Выбираем персональные тарифы, и запоминаем периоды действия их услуг SQL = "SELECT tree_id, title, date1, date2 FROM contract_tree_link WHERE cid=" + cid ; ps = con.prepareStatement( SQL ); rs = ps.executeQuery(); if ( _DEBUG == 1 ){ print("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 ) { print ("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 ) ; } //Для каждой услуги синхронизируем периоды действия, отбрасывая пересекающиеся периоды calcActualServicePeriods( vSidsData ) ; //Тоже самое для услуг Абонплат. calcActualServicePeriods( vNpaySidsData ) ; //Выводим в вывод, список услуг, так, как они будут заведены. Здесь не могут быть пересекающихся периодов для одной услуги. print( "Services must be synchronized with folowing date periods") ; printInternalDataForContract( cid ) ; //Обновляем услуги договора updateSynchronizedServices( cid, 0, con ) ; //Обновляем услуги абонплат договора updateSynchronizedServices( cid, NPAY_MID, con ) ; } public void printInternalDataForContract( int cid ) { print("cid="+cid) ; print("SERVICES:") ; for( int i = 0; i<vSidsData.size(); i++) { vSidsData.get(i).printData() ; } print("NPAY SERVICES:") ; for( int i = 0; i<vNpaySidsData.size(); i++) { vNpaySidsData.get(i).printData() ; } } private void updateSynchronizedServices( int cid, int nPayMid, Connection con ) { String SQLdelNonNeeded = "" ; String SQLsel = "" ; String SQLupd = "" ; String SQLins = "" ; String SQLdel = "" ; Vector 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 запись при необходимости SQLtmp = "SELECT mid FROM contract_module WHERE cid=" + cid + " AND mid=" + NPAY_MID ; PreparedStatement ps = con.prepareStatement( SQLtmp ); rs = ps.executeQuery() ; if( !rs.next() ) { SQLtmp = "INSERT INTO contract_module (cid,mid) VALUES (" + cid + "," + NPAY_MID + ")" ; ps = con.prepareStatement( SQLtmp ); ps.executeUpdate() ; } } SQLdelNonNeeded = "DELETE FROM npay_service_object_" + nPayMid + " WHERE cid=" + cid + " AND sid NOT IN (" + sidslist + ") AND sid NOT IN (" + noSynchroList + ")" ; } if ( deleteNonNeeded == 1 ) { print( 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, date2 ; for( int i = 0; i<vSids.size(); i++) { sd = vSids.get(i) ; int sid = sd.sid ; ps.setInt(1, sid) ; rs = ps.executeQuery() ; 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 = _DATE1_NULL.clone() ; } if ( date2 == null ){ date2 = _DATE2_NULL.clone() ; } //Лишняя услуга, удаляем if ( j >= sd.vDate1.size() ) { psDel.setInt( 1, id ) ; psDel.executeUpdate() ; if (_DEBUG==1){ print( "Delete service with id=" + id + " for service="+sid + " date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; print( "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, sd.vDate1.get(j) ) ; psUpd.setDate( 2, sd.vDate2.get(j) ) ; psUpd.executeUpdate() ; if (_DEBUG==1){ print( "Update service with id=" + id + " for service="+sid + " previous date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; print( "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, sd.vDate1.get(j) ) ; psIns.setDate( 3, sd.vDate2.get(j) ) ; if (_DEBUG==1){ print( "Insert new service="+sid + " date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " date2=" + TimeUtils.format(date2, "yyyy-MM-dd")) ; print( "psIns" + psIns ) ; } psIns.executeUpdate() ; } } } private String getServiceList(Vector 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 calcActualServicePeriods( Vector vSids ) { prepareInternalData() ; SidsData sd ; Vector vDate1 = new Vector() ; Vector vDate2 = new Vector() ; Date date1 ; Date date2 ; GregorianCalendar date1cal = new GregorianCalendar() ; //Для хранения date1+1 день k = 0 ; for( int i = 0; i<vSids.size(); i++) { sd = vSids.get(i) ; vDate1.clear() ; vDate2.clear() ; for ( j = 0 ; j < sd.vDate1.size() ; )//Отсеиваем ненужные периоды { date1 = sd.vDate1.get(j) ; date2 = sd.vDate2.get(j) ; if ( date1.compareTo( date2) > 0 ) { print("Fatal error, date1=" + TimeUtils.format(date1, "yyyy-MM-dd") + " > date2=" + TimeUtils.format(date2, "yyyy-MM-dd") ) ; print("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 = vDate1.clone() ; sd.vDate2 = vDate2.clone() ; } } private 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 = _DATE1_NULL.clone() ; } if ( date2 == null ) { date2 = _DATE2_NULL.clone() ; } Vector 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) { 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 ) ; } } private void findServicesForTariff2( int mtreeid, int mid, Date date1, Date date2, Connection con ) { 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 } //внутренниц класс для хранения услуги и множества дат date1 и date2 private class SidsData{ public int sid ; public Vector vDate1 ; public Vector vDate2 ; public SidsData() { sid = 0 ; vDate1 = new Vector() ; vDate2 = new Vector() ; } public SidsData( int s ) { sid=s ; vDate1 = new Vector() ; vDate2 = new Vector() ; } public printData() { print ("sid=" + sid) ; for( 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 ; } print (" 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 vSidsData ; private Vector vNpaySidsData ; private String noSynchroList = "1000000" ;//не синхронизировать услуги. }