Доступна более новая версия документации данного модуля.

См. последнюю версию

Разработка компонента чтения данных карточки

Компонент чтения данных предоставляет модулю не зависящий от типа карточки слой получения данных из карточки, необходимых для формирования Карточки обмена сообщениями, а также вспомогательные методы, связанные с получением данных из карточек определенного типа.

Компонент должен реализовывать программный интерфейс 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).