Обработка событий процесса согласования
Материал из BiTel WiKi
Класс скрипта указывается в типе процесса. Скрипт можно дополнить обработкой других событий процесса.
При изменении статуса:
- Оповещает с помощью вспомогательного класса Notificator создателя процесса о переключении его статуса.
Перед закрытием процесса:
- Проверяет, что в списковом параметре PARAMETER_SOGL_LIST проставлены все исполнители с процесса группой USER_GROUP_SOGL_DPT. Списковый параметр должен быть привязан к таблице user.
При закрытии процесса:
- Заполняет текстовый параметр PROCESS_PARAM_REAL_EXECUTE_TIME временем выполнения процесса.
package ru.bgcrm.dyn.ufanet.sogl; import java.sql.Connection; import java.util.Arrays; import java.util.GregorianCalendar; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; import ru.bgcrm.cache.ProcessTypeCache; import ru.bgcrm.dao.ParamValueDAO; import ru.bgcrm.dao.process.StatusChangeDAO; import ru.bgcrm.dyn.ufanet.Notificator; import ru.bgcrm.dyn.ufanet.Notificator.NotificationType; import ru.bgcrm.dyn.ufanet.Thesaurus; import ru.bgcrm.event.Event; import ru.bgcrm.event.ParamChangingEvent; import ru.bgcrm.event.listener.DynamicEventListener; import ru.bgcrm.event.process.ProcessChangedEvent; import ru.bgcrm.event.process.ProcessChangingEvent; import ru.bgcrm.model.BGException; import ru.bgcrm.model.param.ParameterAddressValue; import ru.bgcrm.model.process.Process; import ru.bgcrm.model.process.ProcessExecutor; import ru.bgcrm.model.process.ProcessType; import ru.bgcrm.model.process.StatusChange; import ru.bgcrm.util.sql.ConnectionSet; public class SoglasEventProcessor extends DynamicEventListener { private static final int PROCESS_ACCEPT_STATUS_ID = 46; private static final int PARAMETER_SOGL_LIST = 701; private static final int USER_GROUP_SOGL_DPT = 60; private static final int PROCESS_STATUS_AGREED = 17; private static final int PROCESS_PARAM_REAL_EXECUTE_TIME = 804; private static final Logger log = Logger.getLogger( SoglasEventProcessor.class ); private Connection con; @Override public void notify( Event e, ConnectionSet connectionSet ) throws BGException { con = connectionSet.getConnection(); if( e instanceof ParamChangingEvent ) { onParameterChanging( e ); } else if( e instanceof ProcessChangingEvent ) { onProcessChanging( (ProcessChangingEvent)e ); } else if( e instanceof ProcessChangedEvent ) { onProcessChanged( (ProcessChangedEvent)e ); } } private void onProcessChanged( ProcessChangedEvent event ) throws BGException { int statusId = event.getProcess().getStatusId(); Process process = event.getProcess(); ProcessType type = ProcessTypeCache.getProcessType( process.getTypeId() ); int processId = process.getId(); if( event.isStatus() ) { ParamValueDAO paramValueDAO = new ParamValueDAO( con ); ParameterAddressValue address = paramValueDAO.getParamAddress( process.getId(), Thesaurus.Process.PROCESS_PARAMETER_ADDRESS_ID, 1 ); if( address != null ) { String title = "Изменение статуса процесса " + process.getId(); String text = " Статус процесса " + process.getId() + " по адресу " + address.getValue() + " изменился на " + process.getStatusTitle(); Notificator.notificate( new HashSet<Integer>( Arrays.asList( process.getCreateUserId() ) ), title, text, new HashSet<NotificationType>( Arrays.asList( NotificationType.SMS, NotificationType.NEWS, NotificationType.EMAIL ) ) ); } } if( event.isStatus() && type.getProperties().getCloseStatusIds().contains( statusId ) ) { StatusChangeDAO statusChangeDAO = new StatusChangeDAO( con ); List<StatusChange> statusHistory = statusChangeDAO.getProcessStatus( processId, PROCESS_ACCEPT_STATUS_ID ); if( statusHistory.isEmpty() ) { return; } //вычисление времени решения процесса long diffInMillis = process.getCloseTime().getTime() - statusHistory.iterator().next().getDate().getTime(); int diffInDays = (int)diffInMillis / 1000 / 86400; int diffInHours = (int)(diffInMillis / 1000 - 86400 * diffInDays) / 3600; int diffInMins = (int)(diffInMillis / 1000 - 86400 * diffInDays - 3600 * diffInHours) / 60; GregorianCalendar cal = new GregorianCalendar( 0, 0, diffInDays, diffInHours, diffInMins, 0 ); String diffTime = String.format( "%d д. %tH:%tM", diffInDays, cal, cal ); new ParamValueDAO( con ).updateParamText( processId, PROCESS_PARAM_REAL_EXECUTE_TIME, diffTime ); } } private void onProcessChanging( ProcessChangingEvent event ) throws BGException { Process process = event.getProcess(); int processId = process.getId(); if( !event.isStatus() ) { return; } int statusId = event.getStatusChange().getStatusId(); if( statusId != PROCESS_STATUS_AGREED ) { return; } Set<Integer> soglSet = new ParamValueDAO( con ).getParamList( processId, PARAMETER_SOGL_LIST ); for( ProcessExecutor executor : process.getProcessExecutors() ) { if( executor.getGroupId() == USER_GROUP_SOGL_DPT && !soglSet.contains( executor.getUserId() ) ) { throw new BGException( "Процесс должен быть согласован всеми согласователями из списка исполнителей перед закрытием" ); } } } private void onParameterChanging( Event e ) throws BGException { ParamChangingEvent event = (ParamChangingEvent)e; if( event.getParameter() == null || event.getParameter().getId() != PARAMETER_SOGL_LIST ) { return; } Set<Integer> newSet = null; try { newSet = (Set<Integer>)event.getValue(); } catch( Exception ex ) { log.debug( ex ); } if( newSet == null ) { return; } checkPermission( event.getUser().getId(), new ParamValueDAO( con ).getParamList( event.getObjectId(), PARAMETER_SOGL_LIST ), newSet ); } private void checkPermission( int userId, Set<Integer> source, Set<Integer> newSet ) throws BGException { List<Integer> disjSet = (List<Integer>)CollectionUtils.disjunction( source, newSet ); if( disjSet.size() > 1 || (disjSet.size() == 1 && !disjSet.contains( userId )) ) { throw new BGException( "Вы можете проставить согласование только от своего имени" ); } } }