spectrum писал(а):
Неужели никто не делает временную приостановку субдоговоров?
Мы делаем.
Решили проблему собственным скриптом перетирания статусов (5.2):
Код:
package ru.dsi.bgbilling.kernel.scripts;
import bitel.billing.common.TimeUtils;
import bitel.billing.server.contract.bean.ContractStatus;
import bitel.billing.server.contract.bean.ContractStatusManager.ContractStatusManager4Script;
import ru.bitel.bgbilling.kernel.event.EventProcessor;
import ru.bitel.bgbilling.kernel.event.events.ContractSetStatusLogicEvent;
import ru.bitel.bgbilling.kernel.event.events.ContractStatusChangedEvent;
import ru.bitel.bgbilling.kernel.script.server.dev.EventScriptBase;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.sql.ConnectionSet;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
public class MyContractSetStatusLogicEvent
   extends EventScriptBase<ContractSetStatusLogicEvent>
{
   @Override
   public void onEvent( ContractSetStatusLogicEvent event, Setup setup, ConnectionSet connectionSet )
      throws Exception
   {
        Set<Integer> system_uids = new HashSet<Integer>(3);
        system_uids.add(0);//system
        system_uids.add(160);//C3PO
        system_uids.add(178);//CRM
      ContractStatus originalStatus = event.getOriginalStatus();
        print( "userId = "+event.getUserId());
        print( "original status = " + event.getOriginalStatus() );
        print( "status1 = " + event.getStatus1() );
        print( "status2 = " + event.getStatus2() );
      String comment = originalStatus.getComment();
      print(comment);
      print(SubcontractFlagContractStatusChangingEvent.subcontractCommentPrefix);
      if(null==comment){comment="";}
      if(comment.startsWith(SubcontractFlagContractStatusChangingEvent.subcontractCommentPrefix) || system_uids.contains(event.getUserId())){
            //Если либо комментарий статуса начинается с SubcontractFlagContractStatusChangingEvent.subcontractCommentPrefix
            //и мы - субдоговор, либо пользователь = "сервер",
         // (с 23.04.2015) при этом новый статус - не 1 "в отключении" (т.е. статус "в отключении" всегда всё перетирает),
            // то =>
         // => не перекрываем островки статуса "приостановлен"
         // старый статус
         ContractStatus status = event.getStatus1();
            // Приходящий статус
         ContractStatus newStatus = event.getStatus2();
         String statusComment = status.getComment();
         if(statusComment==null){statusComment="";}
            //Обрабатываем только статусы 4 и 1 ("приостановлен", "в отключении"), установленный на конкретном субдоговоре (не спущенный сверху),
            //либо спущенный сверху, но перетираемый скриптом
            // c 23.04.2015 добавили статус 1: его нельзя перетирать по той же логике, что и 4, но он перетирает статус 4 всегда
         if((status.getStatus()==4 || status.getStatus()==1)
               && newStatus.getStatus()!=1 //С 23.04.2015
               && (!statusComment.startsWith(SubcontractFlagContractStatusChangingEvent.subcontractCommentPrefix) || system_uids.contains(event.getUserId()))){
                // менеджер ContractStatusManager, оптимизированный для этого скрипта
            ContractStatusManager4Script csm = new ContractStatusManager4Script( connectionSet.getConnection() );
                //Предыдущий день перед началом нового статуса
            Calendar prevDay = Calendar.getInstance();
            prevDay.setTime( newStatus.getDateFrom() );
            prevDay.add( Calendar.DAY_OF_MONTH, -1 );
                // следующий день после конца нового статуса (или null)
            Calendar nextDay = null;
            if( originalStatus.getDateTo() != null )
            {
               nextDay = Calendar.getInstance();
               nextDay.setTime( newStatus.getDateTo() );
               nextDay.add( Calendar.DAY_OF_YEAR, 1 );
            }
            
            Calendar tmpprev = Calendar.getInstance();
            tmpprev.setTime(status.getDateFrom());
            tmpprev.add( Calendar.DAY_OF_MONTH, -1 );
            
            Calendar tmpnext = Calendar.getInstance();
            if(status.getDateTo()!=null){
               tmpnext.setTime(status.getDateTo());
               tmpnext.add( Calendar.DAY_OF_MONTH, 1 );
            }else{
               tmpnext=null;
            }
                /* 1.
                     * status:...[4444]
                     * new:....[***********?
                     * ->
                     * status:...[4444]
                     * new:....[]......[***?
                     *
                     * и да, мы теряем первый кусок от newStatus, поэтому сразу же его апдейтим (хоть и вне стандартной логики и без ContractStatusChangingEvent)
                    */
            if( TimeUtils.dateBeforeOrEq( newStatus.getDateFrom(), status.getDateFrom() ) && status.getDateTo() != null &&
                      (newStatus.getDateTo() == null || TimeUtils.dateBeforeOrEq( status.getDateTo(), newStatus.getDateTo() )  ) )
               {
                    //Запиливаем первый кусочек:
               if(TimeUtils.dateBefore(newStatus.getDateFrom(), tmpprev.getTime())){
                  ContractStatus tmp = newStatus.clone();
                  tmp.setDateTo(tmpprev.getTime());
                  if(ContractStatusManager4Script.isStatusPeriodValid(tmp)){
                     csm.updateStatus(tmp, event.getUserId());
                     
                     //��������� ������� ������, ���� ���������:
                       ContractStatus statusEvent = new ContractStatus();
                       statusEvent.setContractId(tmp.getContractId());
                       statusEvent.setDateFrom(tmp.getDateFrom());
                       statusEvent.setDateTo(tmp.getDateTo());
                       statusEvent.setStatus(tmp.getStatus());
                       statusEvent.setComment(tmp.getComment());
                       
                       java.util.Date date = new java.util.Date();
                     
                       if ((TimeUtils.dateBeforeOrEq(statusEvent.getDateFrom(), date)) && (
                         (statusEvent.getDateTo() == null) || (TimeUtils.dateBeforeOrEq(date, statusEvent.getDateTo()))))
                       {
                         csm.setContractStatus(statusEvent);
                         ContractStatusChangedEvent changedEvent = new ContractStatusChangedEvent(statusEvent, event.getUserId());
                         EventProcessor.getInstance().publish(changedEvent);
                       }
                     
                  }
               }
                    //Меняем date1 второго кусочка newStatus
               newStatus.setDateFrom(tmpnext.getTime());
               }else
            
            /* 2.
             * status:..[444]
             * new:.......[******?
             * ->
             * status:..[444]
             * new:..........[***? 
             */
            if(status.getDateTo() != null && TimeUtils.dateBeforeOrEq(status.getDateFrom(),newStatus.getDateFrom())){
               newStatus.setDateFrom(tmpnext.getTime());
            }else
            
            /* 3.
             * status:.....[444444?
             * new:.....[*****]
             * ->
             * status:.....[444444?
             * new:.....[*] 
             */
            if(newStatus.getDateTo()!=null && TimeUtils.dateBeforeOrEq(status.getDateFrom(), newStatus.getDateTo())){
               newStatus.setDateTo(tmpprev.getTime());
            }else
            
            /* 4.
             * status:.....[4444!
             * new:.....[*******?
             * or
             * status:.....[4444!
             * new:..........[**? 
             * ->
             * status:.....[4444!
             * new:.....[*]
             * or
             * status:.....[4444!
             * new:..............
             */
            if(status.getDateTo()==null){
                    //либо статус обрезается до кусочка перед нашим диапазоном, либо вырождается
               newStatus.setDateTo(tmpprev.getTime());
            }
            
            event.setProcessed( true );
            csm.recycle();
         }
      }
   }
}
Также есть скрипт, который при установке статуса на супере добавляет устанавливаемым статусам субов префикс "с супердоговора" (используется в предыдущем скрипте):
Код:
package ru.dsi.bgbilling.kernel.scripts;
//import org.apache.log4j.Logger;
import bitel.billing.server.contract.bean.Contract;
import bitel.billing.server.contract.bean.ContractManager;
import bitel.billing.server.contract.bean.ContractStatus;
import ru.bitel.bgbilling.kernel.event.events.ContractStatusChangingEvent;
import ru.bitel.bgbilling.kernel.script.server.dev.EventScriptBase;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.sql.ConnectionSet;
public class SubcontractFlagContractStatusChangingEvent
   extends EventScriptBase<ContractStatusChangingEvent>
{
   public static String subcontractCommentPrefix = "С супердоговора: "; 
   
   @Override
   public void onEvent( ContractStatusChangingEvent event, Setup setup, ConnectionSet connectionSet )
      throws Exception
   {
      int cid = event.getContractId();
      ContractManager cm = new ContractManager(connectionSet.getConnection());
      Contract c = cm.getContractById(cid);
      cm.recycle();
      if(null==c){
         return;
      }
      if(c.isSuper()){
         ContractStatus cs = event.getOriginalStatus();
         if(cs!=null){
            String comment = cs.getComment();
            if(null==comment){comment="";}
            cs.setComment(subcontractCommentPrefix+comment);
         }
      }
   }
}
Уже пару лет проблем не возникает.