ModuleAsyncHandlers.cs
11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
using System;
using System.Collections.Generic;
using System.Linq;
using Sungero.Core;
using Sungero.CoreEntities;
namespace DirRX.CaseArchiving.Server
{
public class ModuleAsyncHandlers
{
public virtual void ChangeCaseFileStageToTransferred(DirRX.CaseArchiving.Server.AsyncHandlerInvokeArgs.ChangeCaseFileStageToTransferredInvokeArgs args)
{
// Переместить дело в архив.
var caseFile = DirRX.LongTermArchive.CaseFiles.Get(args.caseFileId);
caseFile.LTAStageDirRX = DirRX.LongTermArchive.CaseFile.LTAStageDirRX.ArchivedDirRX;
caseFile.LTAArchiveDateDirRX = args.archiveDate;
caseFile.Save();
}
public virtual void TransferDocumentsToArchive(DirRX.CaseArchiving.Server.AsyncHandlerInvokeArgs.TransferDocumentsToArchiveInvokeArgs args)
{
const int MaxIterationCount = 100;
args.Retry = false;
var iteration = args.RetryIteration;
var inventoryId = args.caseInventoryId;
Logger.DebugFormat("CaseArchiving. Старт асинхронного обработчика TransferDocumentsToArchive для описи ИД {0}. Итерация {1}.", inventoryId, iteration);
var inventory = CaseArchiving.CaseInventories.GetAll(x => x.Id == inventoryId).SingleOrDefault();
if (inventory == null || Locks.GetLockInfo(inventory).IsLockedByOther)
{
Logger.DebugFormat("TransferDocumentsToArchive. Не удалось получить опись электронных дел ИД {0}.", inventoryId);
args.Retry = true;
return;
}
else if (inventory.ArchiveState == CaseArchiving.CaseInventory.ArchiveState.Complete)
{
Logger.DebugFormat("TransferDocumentsToArchive. Документы описи ИД {0} уже переданы на архивное храненение.", inventoryId);
return;
}
// ------------------------------------------------------------------------------
// Если описи используются в исходной системе, сформировать архивные контейнеры.
// ------------------------------------------------------------------------------
if (PublicFunctions.Module.Remote.IsCaseInventoryUsedInSourceSystem())
{
// При первом запуске получить список ИД документов для обработки из дел.
if (!inventory.ArchiveState.HasValue || inventory.ArchiveState == DirRX.CaseArchiving.CaseInventory.ArchiveState.Approved)
{
inventory.ProcessingDate = Calendar.Now;
inventory.ArchiveState = CaseArchiving.CaseInventory.ArchiveState.InQueue;
inventory.Save();
var caseFiles = CaseArchiving.PublicFunctions.CaseInventory.Remote.GetCaseFiles(inventory);
foreach (var caseFile in caseFiles)
{
// Отправить каждый документ в обработку.
var documentIds = new List<int>();
foreach (var document in Sungero.Docflow.OfficialDocuments.GetAll(x => x.CaseFile.Equals(caseFile)))
{
var error = Container.PublicFunctions.Module.EnqueueDocumentForInventory(document, inventoryId);
if (error == string.Empty)
documentIds.Add(document.Id);
}
// Зафиксировать список ИД документов, включенных в каждое дело.
caseFile.LTAArchiveDocumentsDirRX = "{" + string.Join(",", documentIds) + "}";
caseFile.Save();
}
// Зафиксировать список ИД дел, включенных в опись.
inventory.ApprovedIds = "{" + string.Join(",", caseFiles.Select(x => x.Id)) + "}";
inventory.Save();
args.Retry = true;
args.NextRetryTime = Calendar.Now.AddMinutes(2);
}
else if (inventory.ArchiveState != CaseArchiving.CaseInventory.ArchiveState.Error)
{
// Убедиться, что этап обработки завершен для всех документов без ошибок.
var allEventLogs = Container.TransferEventLogs.GetAll(x => x.InventoryId == inventoryId).ToList();
var containerStates = allEventLogs.Select(x => x.CurrentState.HasValue ? x.CurrentState.Value.ToString() : "InQueue").Distinct().ToList();
if (!containerStates.Any())
{
containerStates.Add("Error");
Logger.DebugFormat("TransferDocumentsToArchive. ИД описи {0}. На найдены документы для обработки", inventoryId);
}
var currentState = containerStates.Any() ? containerStates.First() : "Error";
Logger.DebugFormat("TransferDocumentsToArchive. ИД описи {0}. Итерация {1}. Статусы контейнеров: {2}. Статус описи {3}.", inventoryId, iteration, string.Join(", ", containerStates), inventory.ArchiveState.Value.ToString());
// Если хотя бы один контейнер ошибочен, прекратить обработку.
if (containerStates.Contains("Error"))
{
inventory.ArchiveState = CaseArchiving.CaseInventory.ArchiveState.Error;
inventory.Save();
args.Retry = false;
}
else if (containerStates.Count == 1 && currentState != "InQueue" && inventory.ArchiveState.Value.ToString() != currentState)
{
// Если все документы обработаны, перевести на след. этап.
inventory.ArchiveState = new Sungero.Core.Enumeration(currentState);
inventory.Save();
if (currentState != "Complete")
{
foreach (var eventLogId in allEventLogs.Select(x => x.Id))
{
var asyncHandler = Container.AsyncHandlers.ProcessNextStageForInventory.Create();
asyncHandler.eventLogId = eventLogId;
asyncHandler.ExecuteAsync();
}
args.Retry = true;
args.NextRetryTime = Calendar.Now.AddMinutes(2);
}
else
{
// После подтверждения приема контейнеров в архиве изменить статус в делах и поставить дату передачи в архив.
var archiveDate = Calendar.Now;
var caseFiles = CaseArchiving.PublicFunctions.CaseInventory.Remote.GetCaseFiles(inventory);
foreach (var caseFileId in caseFiles.Select(x => x.Id))
{
var caseFileHandler = AsyncHandlers.ChangeCaseFileStageToTransferred.Create();
caseFileHandler.caseFileId = caseFileId;
caseFileHandler.archiveDate = archiveDate;
caseFileHandler.ExecuteAsync();
}
inventory.ArchiveDate = archiveDate;
inventory.Save();
args.Retry = false;
}
}
else
{
// Обработка контейнеров не завершена. Необходимо подождать, либо выставить статус Ошибка, если превышено число итераций.
if (iteration > MaxIterationCount)
{
inventory.ArchiveState = CaseArchiving.CaseInventory.ArchiveState.Error;
inventory.Save();
args.Retry = false;
}
else
{
args.Retry = true;
args.NextRetryTime = Calendar.Now.AddSeconds(30);
}
}
Logger.DebugFormat("TransferDocumentsToArchive. ИД описи {0}. Итерация {1}. Новый статус описи: {2}. Запланирован след. запуск: {3}", inventoryId, iteration,
inventory.ArchiveState.Value.ToString(), args.Retry ? args.NextRetryTime.ToString() : "false");
if (inventory.ArchiveState == CaseArchiving.CaseInventory.ArchiveState.Error)
{
// Список ошибочных ИД.
var errorIds = Container.TransferEventLogs.GetAll(x => x.InventoryId == inventoryId && x.CurrentState == Container.TransferEventLog.CurrentState.Error).Select(x => x.Id).ToList();
var message = "Обработка отменена из-за ошибки обработки другого документа описи (ИД " + string.Join(", ", errorIds) + ").";
foreach (var item in Container.TransferEventLogs.GetAll(x => x.InventoryId == inventoryId && !errorIds.Contains(x.Id)))
{
var record = item.Protocol.AddNew();
record.Time = Calendar.Now;
record.Action = Container.Resources.ActionCreateContainer;
record.Message = message;
item.CurrentState = Container.TransferEventLog.CurrentState.Error;
item.Save();
}
}
}
}
else if (PublicFunctions.Module.Remote.IsCaseInventoryUsedInArchiveSystem())
{
// ------------------------------------------------------------------------------
// Если описи используются в архивной системе, проставить отметку в Журнале поступления и выбытия.
// ------------------------------------------------------------------------------
var archiveDate = Calendar.Now;
// Для каждого дела, включенного в опись.
var caseFiles = CaseArchiving.PublicFunctions.CaseInventory.Remote.GetCaseFiles(inventory);
foreach (var caseFile in caseFiles)
{
// Зафиксировать список архивных документов, включенных в дело.
var archiveDocumentIds = DirRX.Storage.PublicFunctions.Module.GetArchiveDocumentIds(caseFile.Id);
foreach (var documentId in archiveDocumentIds)
{
// Связать архивный документ с описью через журнал событий.
var error = DirRX.Storage.PublicFunctions.Module.LinkArchiveDocumentToInventory(documentId, inventoryId);
}
caseFile.LTAArchiveDocumentsDirRX = "{" + string.Join(",", archiveDocumentIds) + "}";
caseFile.LTAArchiveDateDirRX = archiveDate;
caseFile.Save();
}
// Зафиксировать список ИД дел, включенных в опись.
inventory.ApprovedIds = "{" + string.Join(",", caseFiles.Select(x => x.Id)) + "}";
inventory.ArchiveDate = archiveDate;
inventory.ArchiveState = CaseArchiving.CaseInventory.ArchiveState.Complete;
inventory.Save();
}
// Уведомить делопроизводителя и архивиста о завершении обработки описи.
if (args.Retry == false)
CaseArchiving.PublicFunctions.CaseInventory.SendCompletionNotification(inventory);
}
}
}