Разработка компонента чтения данных карточки
Компонент чтения данных предоставляет модулю не зависящий от типа карточки слой получения данных из карточки, необходимых для формирования Карточки обмена сообщениями, а также вспомогательные методы, связанные с получением данных из карточек определенного типа.
Компонент должен реализовывать программный интерфейс IDocumentDataReader
.
Рекомендуется создавать свой компонент на основе абстрактного класса BaseDataReader
(сборка DocsVision.Edi.Runtime.UniversalDocument.dll
). Далее приведена часть класса BaseDataReader
с описанием.
public abstract class BaseDataReaders : IDocumentDataReader
{
public void Initialize(ObjectContext objectContext) (1)
{
ObjectContext = objectContext;
UserSession = ObjectContext.GetService<UserSession>();
documentService = ObjectContext.GetService<IDocumentService>();
}
public string GetDigest(Guid cardId) (2)
{
Document document = GetDocument(cardId);
if (document == null)
{
throw Error.InvalidOperation(Resources.DocumentNotExists, cardId);
}
return document.Description;
}
public string GetFileDigest(Guid cardId, Guid fileId) (3)
{
Document document = GetDocument(cardId);
if (document == null)
{
throw Error.InvalidOperation(Resources.DocumentNotExists, cardId);
}
DocumentFile documentFile = document.Files.FirstOrDefault(item => item.FileVersionRowId == fileId);
if (documentFile == null)
{
throw Error.InvalidOperation(Resources.FileNotExists, fileId, cardId);
}
return GetUniversalDocumentDescription(documentFile.FileVersionRowId, MessageFileType.File) ?? documentFile.FileName;
}
public string GetFileContent(Guid cardId, Guid fileId) (4)
{
Document document = GetDocument(cardId);
if (document == null)
{
throw Error.InvalidOperation(Resources.DocumentNotExists, cardId);
}
DocumentFile documentFile = document.Files.FirstOrDefault(item => item.FileVersionRowId == fileId);
if (documentFile == null)
{
throw Error.InvalidOperation(Resources.FileNotExists, fileId, cardId);
}
if (!UserSession.FileManager.FileExists(documentFile.FileVersionRowId))
{
return null;
}
FileData fileData = UserSession.FileManager.GetFile(documentFile.FileVersionRowId);
using (Stream stream = fileData.OpenReadStream())
{
using (TextReader textReader = new StreamReader(stream))
{
return textReader.ReadToEnd();
}
}
}
public string GetPrintFormContent(Guid cardId) (5)
{
Document document = GetDocument(cardId);
if (document == null)
{
throw Error.InvalidOperation(Resources.DocumentNotExists, cardId);
}
return GetUniversalDocumentPrintContent(document);
}
public string GetReplyFileDigest(Guid cardId, Guid fileId, MessageFileType fileType) (6)
{
return GetUniversalDocumentDescription(fileId, fileType);
}
public string GetReplyFileComment(Guid cardId, Guid fileId, MessageFileType fileType)
{
if (!UserSession.FileManager.FileExists(fileId))
{
return null;
}
try
{
FileData fileData = UserSession.FileManager.GetFile(fileId);
using (Stream stream = fileData.OpenReadStream())
{
switch (fileType)
{
case MessageFileType.InvoiceCorrectionRequest:
case MessageFileType.SignatureRejection:
return InvoiceCorrectionNotice.GetComment(stream);
}
}
}
catch
{
}
return null;
}
public ItemCollection<DocumentRecipientData> GetAllRecipients(Guid cardId) (7)
{
Document document = GetDocument(cardId);
if (document == null)
{
throw Error.InvalidOperation(Resources.DocumentNotExists, cardId);
}
ItemCollection<DocumentRecipientData> recipients = new ItemCollection<DocumentRecipientData>();
var contractSection = document.GetSection(CardDocument.Contract.ID);
if (contractSection.Count == 0)
{
return recipients;
}
BaseCardSectionRow contractRow = (BaseCardSectionRow)contractSection[0];
Guid companyId = contractRow.GetGuid(CardDocument.Contract.PartnerCompany);
if (companyId == Guid.Empty)
{
return recipients;
}
PartnersCompany company = ObjectContext.GetObject<PartnersCompany>(companyId);
if (company != null)
{
recipients.Add(new DocumentRecipientData(ObjectContext.GetObjectRef(company).Id, company.Name));
}
return recipients;
}
public ItemCollection<DocumentSignature> GetActualSignatures(Guid cardId) (8)
{
return null;
}
public ItemCollection<DocumentFileData> GetAllFiles(Guid cardId) (9)
{
Document document = GetDocument(cardId);
if (document == null)
{
throw Error.InvalidOperation(Resources.DocumentNotExists, cardId);
}
return new ItemCollection<DocumentFileData>(document.Files.Where(CheckFile)
.Select(item => new DocumentFileData(item.FileVersionRowId, item.FileName, item.FileType == DocumentFileType.Main)));
}
public ItemCollection<DocumentFileData> GetLastSignedFiles(Guid cardId) (10)
{
return GetSignedFiles(cardId, Guid.Empty);
}
public ItemCollection<DocumentFileData> GetSignedFiles(Guid cardId, Guid signatureGroupId) (11)
{
Document document = GetDocument(cardId);
if (document == null)
{
throw Error.InvalidOperation(Resources.DocumentNotExists, cardId);
}
if (document.MainInfo.SignatureList == null || !document.MainInfo.SignatureList.Signatures.Any())
{
return null;
}
BaseCardSignature lastSignature = signatureGroupId != Guid.Empty
? document.MainInfo.SignatureList.Signatures.FirstOrDefault(item => ObjectContext.GetObjectRef(item).Id == signatureGroupId)
: document.MainInfo.SignatureList.Signatures.OrderByDescending(item => item.TimeStamp).FirstOrDefault();
if (lastSignature == null)
{
return null;
}
ItemCollection<DocumentFileData> result = new ItemCollection<DocumentFileData>();
foreach (DocumentFile documentFile in document.Files.Where(CheckFile))
{
if (UserSession.CardManager.GetCardState(documentFile.FileId) != ObjectState.Existing)
{
continue;
}
VersionedFileCard verFileCard = (VersionedFileCard)UserSession.CardManager.GetCard(documentFile.FileId);
BaseCardSignaturePart filePart = lastSignature.Parts (12)
.FirstOrDefault(item => item.FileVersion == verFileCard.CurrentVersion.VersionId &&
((documentFile.FileType == DocumentFileType.Main &&
documentService.IsDocumentSignaturePartMainFile(item)) ||
(documentFile.FileType == DocumentFileType.Additional &&
documentService.IsDocumentSignaturePartAttachments(item))));
if (filePart == null)
{
continue;
}
result.Add(new DocumentFileData(documentFile.FileVersionRowId, documentFile.FileName,
documentFile.FileType == DocumentFileType.Main, filePart.Signature));
}
return result;
}
public MessageData PrepareMessageData(Guid cardId, string documentType, string documentVersion) (13)
{
Document document = GetDocument(cardId);
if (document.MainInfo.SignatureList == null || !document.MainInfo.SignatureList.Signatures.Any())
{
throw Error.InvalidOperation(Resources.DocumentSignaturesNotExists, cardId);
}
MessageData messageData = new MessageData(cardId, documentType, documentVersion, document.MainInfo.Name);
DateTime? regDate = document.MainInfo[CardDocument.MainInfo.RegDate] as DateTime?;
messageData.DocumentDate = regDate ?? document.CreateDate;
messageData.DocumentComment = document.MainInfo[CardDocument.MainInfo.Content] as string;
Guid numberId = document.MainInfo.GetGuid(CardDocument.MainInfo.RegNumber);
if (numberId != Guid.Empty)
{
BaseCardNumber number = document.Numbers.FirstOrDefault(item => ObjectContext.GetObjectRef(item).Id == numberId);
if (number != null)
{
messageData.DocumentNumber = number.Number;
}
}
return messageData;
}
public MessageFile PrepareFileData(Guid cardId, Guid fileId, Guid signatureId, bool isMain, string tempFolder) (14)
{
return null;
}
// Реализация метода проверки подписи
public SignatureValidation ValidateSignature(Guid cardId, Guid fileId, Guid signatureId) (15)
{
if (cardId == Guid.Empty)
{
throw Error.ArgumentNull("cardId");
}
if (fileId == Guid.Empty)
{
throw Error.ArgumentNull("fileId");
}
if (signatureId == Guid.Empty)
{
throw Error.ArgumentNull("signatureId");
}
if (!UserSession.FileManager.FileExists(fileId))
{
return null;
}
byte[] signatureData = null;
try
{
signatureData = UserSession.AccessManager.GetCryptObject(signatureId);
}
catch
{
}
if (signatureData == null)
{
return null;
}
string signerName = null;
X509Certificate2 certificate = null;
bool isValid = false;
bool isCertificateValid = false;
string validationError = null;
try
{
FileData fileData = UserSession.FileManager.GetFile(fileId);
using (Stream stream = fileData.OpenReadStream())
{
using (BinaryReader reader = new BinaryReader(stream))
{
ContentInfo contentInfo = new ContentInfo(reader.ReadBytes((int)reader.BaseStream.Length));
SignedCms signedCms = new SignedCms(contentInfo, true);
signedCms.Decode(signatureData);
if (signedCms.SignerInfos.Count == 0 || signedCms.Certificates.Count == 0)
{
return null;
}
certificate = signedCms.Certificates[0];
signerName = CertificateHelper.GetCertificateSignerName(certificate);
signedCms.CheckSignature(false);
isValid = true;
signedCms.CheckSignature(new X509Certificate2Collection(certificate), true);
isCertificateValid = true;
}
}
}
catch (Exception ex)
{
validationError = ex.Message;
}
return new SignatureValidation(isValid, isCertificateValid, certificate, signerName, validationError);
}
public string GetInvoiceReplyData(Guid cardId) (16)
{
Document document = GetDocument(cardId);
if (document == null)
{
throw Error.InvalidOperation(Resources.DocumentNotExists, cardId);
}
return GetInvoiceReplyData(document);
}
protected virtual bool CheckFile(DocumentFile documentFile) (17)
{
return false;
}
protected virtual string GetUniversalDocumentDescription(Guid fileId, MessageFileType fileType) (18)
{
return null;
}
protected virtual string GetUniversalDocumentPrintContent(Document document) (19)
{
return null;
}
protected virtual string GetInvoiceReplyData(Document document) (20)
{
return null;
}
}
1 | Инициализируем компонент чтения. При инициализации получаем сервисы API Docsvision, которые потребуются в дальнейшем. |
2 | Реализация метода получения дайджеста карточки. |
3 | Реализация метода получения дайджест файла карточки. |
4 | Реализация метода получения содержимого файла карточки. Для неформализованного документа реализация функциональности не требуется. В стандартной реализации для УПД метод возвращает содержимое приложенного файла XML. |
5 | Реализация метода получения содержимое карточки для печати. Для неформализованного документа реализация функциональности не требуется. В стандартной реализации для УПД используется XSLT-преобразование данных карточки. К печатной форме требуемого вида, отображаемой в карточке УПД. |
6 | Реализация метода получения дайджеста для файла ответа. |
7 | Реализация метода, возвращающего получателей электронного документа. В качестве получателей выбираются все контрагенты из карточки Документ. |
8 | Реализация метода получения актуальных подписей (действительная подпись и действительный сертификат) карточки. |
9 | Реализация метода получения всех приложенных к карточке файлов. |
10 | Реализация метода получения последних подписанных файлов. |
11 | Реализация метода получения файлов карточки, подписанных указанной подписью. |
12 | Только подписанные отдельной подписью файлы. |
13 | Реализация метода подготовки данных для создания сообщения электронного обмена. |
14 | Реализация метода подготовки файла сообщения электронного обмена. Если метод возвращает null будет использована стандартная реализация функции получения MessageFile. Если требуется, может быть реализован собственный метод получения MessageFile , см. подробнее MessageFile — класс. |
15 | По умолчанию выгружаем файл по ID непосредственно при создании сообщения. |
16 | Реализация метода формирования содержимого для ответного сообщения. Используется при формировании ответа на полученный формализованный документ. |
17 | В своей реализации нужно переопределить метод, добавив алгоритм проверки ЭП файла. |
18 | В своей реализации можно переопределить метод, добавив алгоритм получения описания для файла fileId в зависимости от типа сообщения. |
19 | В своей реализации нужно переопределить метод, добавив алгоритм формирования печатной формы для документа document . |
20 | В своей реализации нужно переопределить метода, добавив алгоритм формирования содержимого для ответного сообщения на полученный формализованный документ. Пример реализации в классе DocsVision.Edi.Runtime.UniversalDocument.BuyerInvoiceDataReader (сборка DocsVision.Edi.Runtime.UniversalDocument.dll ). |