ModuleJobs.cs 10.7 KB
using System;
using System.Collections.Generic;
using System.Linq;
using Sungero.Core;
using Sungero.CoreEntities;

namespace DirRX.Storage.Server
{
  public class ModuleJobs
  {

    /// <summary>
    /// Изъять временный доступ к запрошенным документам.
    /// </summary>
    public virtual void RevokeTemporaryAccessToRequestedDocuments()
    {
      // Найти записи журнала Поступление и выбытие документов, у которых есть данные на закладке "Временный доступ".
      var maxDate = Calendar.Now.BeginningOfDay();
      foreach (var eventLogId in Storage.ArchiveEventLogs.GetAll(log => log.DocumentId.HasValue && log.CurrentState != Storage.ArchiveEventLog.CurrentState.Destroyed &&
                                                                 log.TemporaryAccess.Any(ta => ta.Status == Storage.ArchiveEventLogTemporaryAccess.Status.Granted && ta.TermTo < maxDate))
               .Select(log => log.Id))
      {
        try
        {
          var asyncHandler = AsyncHandlers.RevokeTemporaryAccessRights.Create();
          asyncHandler.eventLogId = eventLogId;
          asyncHandler.ExecuteAsync();
        }
        catch (Exception e)
        {
          Logger.Debug(e.ToString());
        }
      }
    }

    /// <summary>
    /// Отправить уведомление о необходимости подтвердить синхронизацию.
    /// </summary>
    public virtual void SendNotificationToConfirmSync()
    {
      Functions.Module.SendNotificationToConfirmSync();
    }
    
    /// <summary>
    /// Выполнить плановую проверку наличия, целостности, неизменности контейнеров.
    /// </summary>
    public virtual void VerifyContainers()
    {
      Logger.DebugFormat("Storage. Старт фонового процесса VerifyContainers");
      
      // Перед началом проверки первого контейнера необходимо сформировать сессию проверки, с единым идентификатором для всех контейнеров.
      // Сессии отдельно нигде не хранятся. В качестве идентификатора используется свойство "JobStartDate" в Журнале поступления и выбытия.
      var startDate = Calendar.Now;
      var verificationReason = ArchiveEventLogs.Resources.DefaultVerificationReason;
      var verificationResponsible = Storage.PublicFunctions.Module.Remote.GetVerificationResponsible();
      var archiveEventIds = new List<int>();
      
      // Запланировать проверку контейнеров с датой верификации меньше текущей.
      foreach (var archiveEvent in Storage.ArchiveEventLogs.GetAll(x => x.DocumentId.HasValue && x.CurrentState != Storage.ArchiveEventLog.CurrentState.InProcess &&
                                                                   x.CurrentState != Storage.ArchiveEventLog.CurrentState.Destroyed &&
                                                                   (!x.VerificationResult.HasValue || x.VerificationResult.Value == Storage.ArchiveEventLog.VerificationResult.Succeeded) &&
                                                                   x.VerificationDate <= startDate))
      {
        try
        {
          archiveEvent.JobStartDate = startDate;
          archiveEvent.JobEndDate = null;
          archiveEvent.VerificationResult = null;

          archiveEvent.VerificationReason = verificationReason;
          archiveEvent.VerificationResponsible = verificationResponsible;

          Functions.ArchiveEventLog.AddEventHistory(archiveEvent,
                                                    Storage.ArchiveEventLogs.Resources.Operation_Verification,
                                                    Storage.ArchiveEventLog.CurrentState.InProcess,
                                                    ArchiveEventLogs.Resources.MessageVerificationStarted);
          archiveEventIds.Add(archiveEvent.Id);
        }
        catch (Exception e)
        {
          Logger.DebugFormat("VerifyContainers. Не удалось сохранить Журнал поступления и выбытия с ИД {0}", archiveEvent.Id);
          Logger.Debug(e.ToString());
        }
      }
      
      if (archiveEventIds.Any())
      {
        // Запустить проверку для каждого из выбранных контейнеров.
        foreach (var archiveEventId in archiveEventIds)
        {
          var asyncHandler = Storage.AsyncHandlers.VerifyContainer.Create();
          asyncHandler.eventId = archiveEventId;
          asyncHandler.ExecuteAsync();
        }
        
        // Запустить отслеживание завершения проверки для отправки уведомления.
        var checkAsyncHandler = Storage.AsyncHandlers.SendNotificationAfterVerification.Create();
        checkAsyncHandler.eventId = archiveEventIds.First();
        checkAsyncHandler.ExecuteAsync();
      }
    }

    /// <summary>
    /// Улучшить ЭП архивных документов.
    /// </summary>
    public virtual void ImproveArchiveDocumentsSignature()
    {
      var containers = ArchiveEventLogs.GetAll().Where(x => x.NextImproveDate != null &&
                                                       x.NextImproveDate <= Calendar.Now &&
                                                       x.ContainerSignatures.Any() &&
                                                       (x.CurrentState == Storage.ArchiveEventLog.CurrentState.Complete || x.CurrentState == null)).ToList();
      if (containers.Any())
      {
        foreach (var container in containers)
        {
          var isElectronic = true;
          var document = Sungero.Docflow.OfficialDocuments.Get(container.DocumentId.Value);
          if (document != null)
          {
            var caseFile = DirRX.LongTermArchive.CaseFiles.As(document.CaseFile);
            if (caseFile != null)
              isElectronic = !caseFile.LTAIsPaperDirRX.Value;
          }
          if (isElectronic)
          {
            Storage.Functions.Module.AddArchiveEventLog(container.TempGuid, Storage.ArchiveEventLogs.Resources.Operation_Improve, Storage.ArchiveEventLog.CurrentState.InQueue, string.Empty);
            var asyncHandler = Storage.AsyncHandlers.ImproveArchiveDocumentSignature.Create();
            asyncHandler.eventId = container.Id;
            asyncHandler.ExecuteAsync();
          }
        }
        
        var ids = string.Join(",", containers.Select(i => i.Id.ToString()).ToArray());
        var asyncHandlerChecker = Storage.AsyncHandlers.ImproveProcessChecker.Create();
        asyncHandlerChecker.Ids = ids;
        asyncHandlerChecker.ExecuteAsync();
      }
    }
    
    /// <summary>
    /// Уничтожить тела документов.
    /// </summary>
    public virtual void DestroyDocumentsBodies()
    {
      Logger.Debug("Job. DestroyDocumentsBodies. Старт");
      
      var archiveEventLogList = DirRX.Storage.ArchiveEventLogs
        .GetAll(x => (x.DestructionAct != null) && (x.CurrentState != Storage.ArchiveEventLog.CurrentState.Destroyed));
      
      if (!archiveEventLogList.Any())
      {
        Logger.Debug("Job. DestroyDocumentsBodies. Документы к уничтожению не найдены");
        return;
      }
      // Словарь, ключ - документ к удалению, значение - акт уничтожения.
      var archiveDocumentsToDestroy = new Dictionary<Sungero.Content.IElectronicDocument, DirRX.Storage.IDestructionAct>();
      
      // Заполнить словарь.
      foreach (var archiveEventLogEntry in archiveEventLogList)
      {
        var archiveDocument = Sungero.Content.ElectronicDocuments.GetAll(x => Equals(x.Id, archiveEventLogEntry.DocumentId)).SingleOrDefault();
        archiveDocumentsToDestroy.Add(archiveDocument, archiveEventLogEntry.DestructionAct);
      }
      
      // Для каждого документа запустить асинхронный обработчик.
      foreach (var archiveDocumentToDestroy in archiveDocumentsToDestroy)
      {
        var job = AsyncHandlers.DestroyDocumentsBodies.Create();
        job.documentId = archiveDocumentToDestroy.Key.Id;
        job.actId = archiveDocumentToDestroy.Value.Id;
        job.ExecuteAsync();
      }
      
      var destructionActIds = new List<int>();
      foreach (var archiveDocumentToDestroy in archiveDocumentsToDestroy)
      {
        destructionActIds.Add(archiveDocumentToDestroy.Value.Id);
      }
      
      foreach (var destructionActId in destructionActIds.Distinct())
      {
        var asyncHandlerChecker = Storage.AsyncHandlers.CheckDestroyDocumentsBodies.Create();
        asyncHandlerChecker.Id = destructionActId;
        asyncHandlerChecker.ExecuteAsync();
      }
    }

    /// <summary>
    /// Сформировать акты о выделении дел к уничтожению .
    /// </summary>
    public virtual void CreateCaseDestructionActs()
    {
      Logger.Debug("Job. CreateCaseDestructionActs. Старт");
      
      // Получить список всех дел к уничтожению.
      var allCaseFiles = PublicFunctions.Module.Remote.GetCaseFilesToDestroy();
      
      if (allCaseFiles.Any())
      {
        // Создавать акты в разрезе подразделений, если используется установка "Вести дела в разрезе подразделений".
        var isCreateByDepartments = CaseArchiving.PublicFunctions.Module.Remote.IsCreateCaseInventoryByDepartments();
        
        // Создавать акты в разрезе состояний дел (завершенные или архивные).
        foreach (var stage in allCaseFiles.Select(x => x.LTAStageDirRX).Distinct())
        {
          if (isCreateByDepartments)
          {
            foreach (var department in allCaseFiles.Where(x => x.Department != null && x.LTAStageDirRX == stage).Select(x => x.Department).Distinct())
            {
              var caseFilesForOneAct = allCaseFiles.Where(x => x.LTAStageDirRX == stage && x.Department == department);
              PublicFunctions.Module.Remote.CreateDestructionAct(caseFilesForOneAct.ToList(), null, department);
            }
          }
          else
          {
            var caseFilesForOneAct = allCaseFiles.Where(x => x.LTAStageDirRX == stage);
            PublicFunctions.Module.Remote.CreateDestructionAct(caseFilesForOneAct.ToList(), null, null);
          }
        }
        
      }
    }

  }
}