ModuleServerFunctions.cs 11.6 KB
using System;
using System.Collections.Generic;
using System.Linq;
using Sungero.Core;
using Sungero.CoreEntities;

namespace DirRX.CaseArchiving.Server
{
  public class ModuleFunctions
  {
    /// <summary>
    /// Получить опись по ИД.
    /// </summary>
    /// <param name="id">ИД документа.</param>/// 
    /// <returns>Опись электронных дел.</returns>
    [Public, Remote(IsPure = true)]
    public virtual ICaseInventory GetCaseInventory(int id)
    {
      var result = CaseInventories.Null;
      AccessRights.AllowRead(() => { result = CaseInventories.GetAll(x => x.Id == id).SingleOrDefault(); });
      return result;
    }

    /// <summary>
    /// Получить список архивистов из роли.
    /// </summary>
    /// <returns>Список сотрудников.</returns>
    [Remote(IsPure = true), Public]
    public virtual List<Sungero.Company.IEmployee> GetEmployeesForArchivistRole()
    {
      var archivistRole = Roles.GetAll(x => x.Sid == Constants.Module.Initialize.ArchivistRoleGuid).FirstOrDefault();
      return archivistRole.RecipientLinks.Where(x => x.Member != null  && Sungero.Company.Employees.Is(x.Member)).Select(x => Sungero.Company.Employees.As(x.Member)).ToList();
    }
    
    /// <summary>
    /// Установить значение параметра.
    /// </summary>
    /// <param name="paramKey">Имя параметра.</param>
    /// <param name="paramValue">Значения параметра.</param>
    /// <remarks>Обертка для вызова с клиента для функции InsertOrUpdateDocflowParam.</remarks>
    [Remote, Public]
    public virtual void SetDocflowParam(string paramKey, string paramValue)
    {
      Sungero.Docflow.PublicFunctions.Module.InsertOrUpdateDocflowParam(paramKey, paramValue);
    }
    
    /// <summary>
    /// Получить значение настройки "Формировать описи в разрезе подрезделений".
    /// </summary>
    /// <returns>true/false.</returns>
    [Remote(IsPure = true), Public]
    public virtual bool IsCreateCaseInventoryByDepartments()
    {
      return Sungero.Docflow.PublicFunctions.Module.Remote.GetDocflowParamsStringValue(CaseArchiving.PublicConstants.Module.DocflowParams.CreateCaseInventoryByDepartmentsKey) == "true";
    }
    
    /// <summary>
    /// Получить значение настройки "Описи формируются в исходной системе".
    /// </summary>
    /// <returns>true/false.</returns>
    [Remote(IsPure = true), Public]
    public virtual bool IsCaseInventoryUsedInSourceSystem()
    {
      return Sungero.Docflow.PublicFunctions.Module.Remote.GetDocflowParamsStringValue(CaseArchiving.PublicConstants.Module.DocflowParams.UseCaseInventoryInSourceSystemKey) == "true";
    }

    /// <summary>
    /// Получить значение настройки "Описи формируются в архивной системе".
    /// </summary>
    /// <returns>true/false.</returns>
    [Remote(IsPure = true), Public]
    public virtual bool IsCaseInventoryUsedInArchiveSystem()
    {
      return Sungero.Docflow.PublicFunctions.Module.Remote.GetDocflowParamsStringValue(CaseArchiving.PublicConstants.Module.DocflowParams.UseCaseInventoryInArchiveSystemKey) == "true";
    }
    
    /// <summary>
    /// Получить виды документов для типа карточки "Описи электронных дел".
    /// </summary>
    /// <returns>Виды документов.</returns>
    [Remote(IsPure = true), Public]
    public virtual IQueryable<Sungero.Docflow.IDocumentKind> GetCaseInvenoryDocumentKinds()
    {
      // Отсортировать список, чтобы первым был вид документа по умолчанию.
      var externalLink = Sungero.Docflow.PublicFunctions.Module.GetExternalLink(Constants.Module.Initialize.DocumentKindTypeGuid, Constants.Module.Initialize.CaseInventoryDocumentKind);
      
      return Sungero.Docflow.DocumentKinds.GetAll().Where(x => x.Id == externalLink.EntityId).OrderBy(x => x.IsDefault == true ? 0 : x.Id);
    }

    /// <summary>
    /// Получить виды документов для типа карточки "Описи бумажных дел".
    /// </summary>
    /// <returns>Виды документов.</returns>
    [Remote(IsPure = true), Public]
    public virtual IQueryable<Sungero.Docflow.IDocumentKind> GetPaperCaseInvenoryDocumentKinds()
    {
      // Отсортировать список, чтобы первым был вид документа по умолчанию.
      var externalLink = Sungero.Docflow.PublicFunctions.Module.GetExternalLink(Constants.Module.Initialize.DocumentKindTypeGuid, Constants.Module.Initialize.PaperCaseInventoryDocumentKind);
      
      return Sungero.Docflow.DocumentKinds.GetAll().Where(x => x.Id == externalLink.EntityId).OrderBy(x => x.IsDefault == true ? 0 : x.Id);
    }
    
    /// <summary>
    /// Получить список дел.
    /// </summary>
    /// <param name="stage">Состояние дела в ДА.</param>
    /// <returns>Список записей справочника "Номенклатура дел".</returns>
    [Remote(IsPure = true), Public]
    public virtual System.Linq.IQueryable<DirRX.LongTermArchive.ICaseFile> GetCaseFiles(Sungero.Core.Enumeration? stage)
    {
      if (stage.HasValue)
        return LongTermArchive.CaseFiles.GetAll(x => x.LTAStageDirRX == stage);
      else
        return LongTermArchive.CaseFiles.GetAll();
    }
    
    /// <summary>
    /// Получить количество документов в деле.
    /// </summary>
    /// <param name="caseFile">Дело.</param>
    /// <returns>Количество дел.</returns>
    [Remote(IsPure = true), Public]
    public static int GetDocumentsTotal (int caseFileId)
    {
      return Sungero.Docflow.OfficialDocuments.GetAll(x => x.CaseFile != null && x.CaseFile.Id.Equals(caseFileId)).Count();
    }
    
    /// <summary>
    /// Создать описи по списку дел.
    /// </summary>
    /// <param name="year">Год.</param>
    /// <param name="caseFiles">Список дел.</param>
    /// <param name="archivist">Архивист (приемщик дел).</param>
    /// <returns>Список созданных описей.</returns>
    [Public, Remote]
    public virtual List<CaseArchiving.ICaseInventory> CreateCaseInventories(int year, List<DirRX.LongTermArchive.ICaseFile> caseFiles, Sungero.Company.IEmployee archivist)
    {
      var result = new List<CaseArchiving.ICaseInventory>();
      
      if (caseFiles.Any())
      {
        // Если архивист не указан, взять из роли.
        if (archivist == null)
        {
          var role = Roles.GetAll(x => x.Sid == Constants.Module.Initialize.ArchivistRoleGuid).FirstOrDefault();
          if (role != null && role.RecipientLinks.Any())
            archivist = Sungero.Company.Employees.As(role.RecipientLinks.First().Member);
        }
        
        // Сгруппировать дела по видам описей, подразделениям, ответственным.
        var isCreateInventoryByDepartments = PublicFunctions.Module.Remote.IsCreateCaseInventoryByDepartments();
        var data = caseFiles.GroupBy(x => new
                                     {
                                       DocumentKind = x.LTAInventoryKindDirRX,
                                       Department = isCreateInventoryByDepartments ? x.Department : Sungero.Company.Departments.Null,
                                       Responsible = x.LTAResponsibleDirRX
                                     })
          .Select(y => new { DocumentKind = y.Key.DocumentKind, Department = y.Key.Department, Responsible = y.Key.Responsible, CaseFiles = y.ToList() });
        
        foreach (var item in data)
        {
          // HACK Без формирования документа в отдельной транзакции для БД Postgres падает ошибка Illegal attempt to associate a collection with two open sessions
          var caseInventory = CaseArchiving.CaseInventories.Null;
          using (new Sungero.Domain.Session(true, false))
          {
            var document = CaseArchiving.CaseInventories.Create();
            // Заполнить карточку описи.
            document.EndOfYear = Calendar.GetDate(year, 12, 31);
            document.Responsible = item.Responsible;
            document.DocumentKind = item.DocumentKind;
            document.Subject = item.DocumentKind.DisplayValue;
            document.BusinessUnit = (item.Department != null ? item.Department : item.Responsible.Department).BusinessUnit;
            document.Department = item.Department;
            document.Archivist = archivist;
            
            if (item.Responsible != null)
              document.AccessRights.Grant(item.Responsible, DefaultAccessRightsTypes.FullAccess);
            
            if (archivist != null)
              document.AccessRights.Grant(archivist, DefaultAccessRightsTypes.Change);
            
            document.State.Properties.BusinessUnit.IsRequired = false;
            document.State.Properties.Department.IsRequired = false;
            document.Save();
            caseInventory = document;
          }
          
          // Связать дела с описью.
          foreach (var caseFile in item.CaseFiles)
            DirRX.LongTermArchive.PublicFunctions.CaseFile.UpdateInventory(caseFile, caseInventory);
          
          result.Add(caseInventory);
        }
      }
      return result;
    }
    
    /// <summary>
    /// Получить список описей.
    /// </summary>
    /// <returns>Список описей.</returns>
    [Remote(IsPure = true), Public]
    public virtual IQueryable<ICaseInventory> GetCaseInventories()
    {
      return CaseArchiving.CaseInventories.GetAll();
    }
    
    /// <summary>
    /// Отправить опись на верификацию.
    /// </summary>
    /// <param name="document">Опись электронных дел.</param>
    [Public]
    public virtual void SendCaseInventoryForVerification(CaseArchiving.ICaseInventory document)
    {
      var task = CaseArchiving.VerificationTasks.Create();
      task.DocumentGroup.CaseInventories.Add(document);
      task.Start();
    }

    /// <summary>
    /// Отправить опись на согласование по регламенту.
    /// </summary>
    /// <param name="document">Опись электронных дел.</param>
    /// <param name="author">Инициатор.</param>
    [Public]
    public virtual void SendCaseInventoryForApproving(CaseArchiving.ICaseInventory document, IUser author)
    {
      // Проверить не создана ли уже задача на согласование (например, вручную).
      var createdTasks = Sungero.Docflow.PublicFunctions.Module.Remote.GetApprovalTasks(document);
      
      if (!createdTasks.Any())
      {
        // Создать задачу на согласование по регламенту.
        var approvalTask = Sungero.Docflow.PublicFunctions.Module.Remote.CreateApprovalTask(document);
        
        approvalTask.Author = author;
        approvalTask.StartedBy = author;
        approvalTask.Signatory = document.Archivist;
        approvalTask.Save();
        
        approvalTask.ReqApprovers.Clear();
        approvalTask.ReqApprovers.AddNew().Approver = document.Archivist;
        approvalTask.Save();
        approvalTask.Start();
      }
    }
  }
}