Как поставить штамп с информацией о ЭП на документ

10 20

Сталкивались на предприятии с ситуацией, когда бухгалтерия на распечатанный, подписанный ЭП документ требует поставить живую подпись? «Как же так?!» - возмущаются пользователи - «Есть же электронная подпись». А в бухгалтерии все равно нужно подтверждение, что документ подписан. И желательно, чтобы «вот прямо» на распечатанном документе. Как в банке проставляют штамп «Исполнено» на платежках:

Давайте обсудим, как это можно сделать в DIRECTUM.

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

Исходя из всего перечисленного можно выработать следующий алгоритм:

  1. Определяем, подписан ли вообще документ.
  2. Ищем последнюю подписанную версию.
  3. Формируем изображение штампа с текстом, содержащим информацию о подписях.

Примерно, вот так:

  1. Экспортируем последнюю подписанную версию документа.
  2. Преобразовываем выгруженный документ в формат pdf.
  3. Проставляем на него штамп.
  4. Импортируем pdf-документ со штампом в новую версию электронного документа.
  5. Распечатываем документ.

 

 

 

 

 

 

 

 

 

 

 

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

Предложенный алгоритм был реализован в виде прикладной функции DIRECTUM на версии 5.2. Напомню, что функции по установке штампов на pdf-документах появились в версии 5.0.

Итак, код функции:

  //Делаем проверку парметра функции EDocument. EDocument – переданный в функцию документ, преобразование которого необходимо выполнить
  // Не указан параметр "%s".
  Assert(Assigned(EDocument); LoadStringFmt('DIRE434A6BC_59D8_4AF4_A58D_5105D7C60DF6'; 'COMMON'; 'EDocument'))
//Блокируем документ от изменения
  EDocument.Lock
  EMPTY_STR = ''
  NOT_FOUND = -1
  PDF = 'PDF'
  
  // Тип документа по расширению
  Extension = EDocument.Info.Editor.Extension
  
  // Если уже PDF, подтвердить постановку штампов  
  if Extension == PDF
    YES = 'Да'
    NO = 'Нет'
    Answer = MessageBox(ATTENTION_CAPTION; 'У данного документа уже есть версия в формате PDF^Создать новую версию документа со штампами на основе последней действующей подписанной версии?'; YES & "|" & NO; NO; NO)
    if Answer == NO
      EDocument.UnLock
      Exit()
    endif
  endif
  // Найти номер последней действующей подписанной версии
  LastVersionNumber = NOT_FOUND
  Versions = EDocument.Versions
  Index = 0
  while Index < Versions.Count
    Version = Versions.Values(Index)
    if Version.CurrentState = vsActive and Version.Signed
      LastVersionNumber = Version.Number
      Extension = Version.Editor.Extension
    endif
    Index = Index + 1
  endwhile
  
  if LastVersionNumber = NOT_FOUND
    EDocument.UnLock
    Raise(CreateException("ENoActiveVersionFound"; "У документа нет ни одной действующей подписанной версии"; ecWarning))
  endif

  // Экспортировать последнюю подписанную версию
  ExportFile = Format("%s%s.%s"; ArrayOf(GetTempFolder(); EDocument.ID; Extension))
  DeleteFile(ExportFile)
  EDocument.Export(LastVersionNumber; ExportFile; false; false; false)

  try 
   // Преобразовать в PDF, если экспортировали версию, которая не являлась pdf-документом.
   if Extension <<>> 'PDF'
      WSDLFileName = GetConstant('DCTSConvertToPDFWSDL')
      PDFFile = Format("%s%s.pdf"; ArrayOf(GetTempFolder(); EDocument.ID))
      DeleteFile(PDFFile)
      DCTSConvertFileToPDF(WSDLFileName; ExportFile; PDFFile)
    else
      PDFFile = ExportFile
    endif      
    // Общие параметры штампов
    StampFilename = GetTempFolder() & "stamp.png"
    STAMP_COLOR = '000000' // Черный
    STAMP_FONT_FACE = 6 // Times New Roman
    STAMP_FONT_SIZE = 20
  
    // ШТАМП С ДАННЫМИ ЭЦП ДОКУМЕНТА
    SignatureField        = EMPTY_STR // Часть штампа с информацией об ЭЦП
    SignatureDate         = EMPTY_STR
    SerialNumber          = EMPTY_STR
    CertificateValidFrom  = EMPTY_STR
    CertificateValidTo    = EMPTY_STR
    SubjectName           = EMPTY_STR
    SignatureAuthor       = EMPTY_STR
    // Собрать информацию о параметрах ЭП
    SignatureFieldStringList =  CreateStringList()
    Signatures = EDocument.Versions.Values(LastVersionNumber-1).Signatures
    if Signatures.Count > 0
      SignatureIndex = Signatures.Count - 1
      while SignatureIndex >= 0
        Signature = Signatures.Values(SignatureIndex)
          //Найти утверждающую подпись
          if Signature.SignatureType <> stNone 
            AuthorUser = Signature.Author
            Certificate   = Signature.Certificate            
            SerialNumber = Certificate.SerialNumber
            if Assigned(AuthorUser) and SerialNumber <<>> EMPTY_STR
              SignatureAuthor = AuthorUser.FullName
              SignatureType = IfThen(Signature.SignatureType = stApproving; 'утверждающая ЭП'; 'визирующая ЭП') 
              CertificateValidFrom = FormatDate('D.M.YY'; Certificate.ValidFromDate)
              CertificateValidTo = FormatDate('D.M.YY'; Certificate.ValidToDate)
              SignatureDate = FormatDate('D.M.YY'; Signature.Date)
              ValidText = IfThen(Signature.IsValid; 'ЭП достоверна'; 'ЭП не достоверна')
              SignatureField = Format("Подписан ЭП: %s   Серт.: %s, действ. %s - %s, тип: %s, достоверность: %s";
                                      ArrayOf(SignatureAuthor;
                                              SerialNumber;
                                              CertificateValidFrom;
                                              CertificateValidTo;
                                              SignatureType;
                                              ValidText))
              SignatureFieldStringList.Add(SignatureField)
            endif
          endif
        SignatureIndex = SignatureIndex - 1
      endwhile
      
    // Сегодня ДД.ММ.ГГГГ
      CurrentDate = FormatDate('D.M.YY'; Today())
      SignatureFieldStringList.Delimiter = CR
      StampText = CurrentDate & ', ' & SignatureFieldStringList.DelimitedText
      // Рамка штампа
      STAMP_BORDER = 1
      STAMP_BORDER_THICKNESS = 8
      // Сгенерировать изображение с текстом, содержащим информацию о параметрах ЭП 
      GenerateTextImage(StampText; STAMP_BORDER; STAMP_BORDER_THICKNESS; STAMP_COLOR; STAMP_FONT_SIZE; STAMP_FONT_FACE; StampFilename; 0)
    
      // Добавить штамп в PDF-документ
      STAMP_SCALE = 30

      PagesMode = 2

      AddImageToPDFFile(PDFFile; StampFilename;;; PagesMode; nil; STAMP_SCALE) 
      EDocument.UnLock
      // Импортировать документ в новую версию электронного документа
      EDocument.ImportFromFile(-1; 'Версия со штампами ЭЦП в PDF на основе последней подписанной'; PDFFile)
      OpenFile(PDFFile)
    endif
  except
    EDocument.UnLock
  endexcept  

В результате работы данного функционала в электронном документе появится версия, содержимое которой неизменно и которая содержит штамп с информацией о ЭП, поставленных на документе.

 

Валентина Писанова

Забавно, конечно, что если "прикопаться", то это уже совершенно не тот документ, который был подписан этой самой подписью smiley

Алексей Язынин

Так и бумажный документ, на котором дополнительно поставили "живую" подпись - уже "совсем не тот документ".

Валентина Писанова

В меньшей степени smiley

Марина Швецова

В штампе не хватает ИД документа и номера подписанной версии

Вера Карманова
Забавно, конечно, что если "прикопаться", то это уже совершенно не тот документ, который был подписан этой самой подписью

Да ). Но теперь по распечатанному документу можно узнать, кто подписывался под документом с данным текстом.

Вера Карманова
В штампе не хватает ИД документа и номера подписанной версии

Эту информацию не сложно добавить в текст, из которого будет формироваться изображение штампа. Что-то добавить, что-то убрать - это уже на усмотрение пользователей, программистов системы.

Алексей Семакин

Интересно, насколько (и почему) такое решение устраивает бухгалтерию? Если они не доверяют электронной подписи, которую собственноручно поставил подписывающий (иначе зачем требуют живую подпись на распечатанном документе?), то за вывод штампа в документ отвечает вообще другой человек.
Я готов согласиться с тем, что штамп в документе может упростить визуальное восприятие электронной подписи при условии, что я доверяю самой подписи. Но я сомневаюсь, что наличие такого штампа само по себе хоть что-то подтверждает.

Вера Карманова

Хочу отметить, что были обращения от клиентов с просьбой реализовать такой функционал. Бухгалтерии нужно подшивать документы, и чтобы именно на этой распечатанной бумажке было видно, что документ подписан. Вариант с распечаткой информации о подписях на отдельном документе из не устраивает.

Алексей Семакин

Я у одного заказчика делал аналогичную штуковину, Вера. Да чего уж там — почти в точности такую же :) Там на штамп возлагалась простая функция: показать кто, когда и каким сертификатом подписал документ. То есть штамп не заменял собою ЭП и не освобождал от обязанности контролировать наличие подписи на электронном документе и валидность сертификата. Из твоего последнего комментария вижу, что в данном случае задача была какой-то такой же.

Алексей Семакин

В дополнение к первому комментарию Валентины скажу: документ со штампом не просто "не тот", а теоретически настолько не тот, что его вообще не стоило бы заносить в систему — только на печать. Потому что при наличии умысла у программиста есть возможность внести изменения в текст документа перед преобразованием в PDF и постановкой штампа. Возможно, я излишне параноик.

Вера Карманова

Да, так и есть. Нужно знать, к кому идти, если будут вопросы к документу.

Артем Шуткин

Простановка штампа ЭП на документе, мне кажется - функционал, который должен быть в стандартной системе по умолчанию.

На текущем проекте реализовывали подобный механизм, правда с особенностями по сравнению с предложенным алгоритмом:

  1. Определяем, подписан ли вообще документ. Искали только по утверждающим подписям. Если нет утверждающих, то кнопка распечатки штампа в ТКЭД дизейблилась.
  2. Если версий, подписанных утверждающей ЭП, несколько, то запрашиваем версию.
  3. Если на документе несколько утверждающих ЭП, то запрашиваем, штамп каких ЭП вставить. По факту при согласовании кто-то из согласующих может подписать по ошибке утверждающей ЭП. во вторых- утверждающих документ может быть несколько (определили с Заказчиком логичное ограничение до 3 штампов, иначе штампы на полстраницы и четвертый обрезается).
  4. Формируем изображение штампа с текстом, содержащим информацию о подписях. Дополнительное: В тексте указываем также имя пользователя, если ЭП поставлена по замещению. Часто бывает секретарь работает за руководителя.

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

    5. Преобразовываем выбранную версию документа в pdf.

    6. Проставляем выбранные штампы.

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

В планах развития функционала из пожеланий:

  1. Запрос языка штампа. т.к. есть необходимость отправлять документы и в иностранные компании;
  2. Т.к. реализовывается функционал для группы компаний, то возможность задавать различный логотип в штампе для каждой компании.
Алексей Барышев

Здравствуйте. Качество текста в штампе почему-то очень низкое. Я имею в виду четкость, резкость. Штамп как будто низкого разрешения, текст не четкий. Пробовал разные параметры менять, но красивого результата не добился. Так и должно быть? Прикладываю кусочек документа. Видно, что качество шрифтов в тексте и штампе разное

 

Компания DIRECTUM: обновлено 17.12.2019 в 11:18
Александр Чугунов

Алексей, чтобы штамп был красивый надо его генерить размером раза в 2 больше, потом при вставке сжимать, там коэффициент задавать можно.

Николай Толстобоков

Поставил на отдельную кнопку, но выдает ошибку, "Значение переменной EDocument" не определено, ошибка в строке 3

Assert(Assigned(EDocument); LoadStringFmt('DIRE434A6BC_59D8_4AF4_A58D_5105D7C60DF6'; 'COMMON'; 'EDocument'))
//Блокируем документ от изменения

Как указать значение переменной этой? что я делаю не так?

Разбираемся в вопросе https://club.directum.ru/question/71614

Елена Питомцева: обновлено 21.09.2017 в 08:11
Сергей Ершов

Добавил кнопку  карточку, все работает.

Можно ли эту кнопку вывести в контекстное меню документа, что бы каждый раз не открывать карточку, каждого документа?

Если можно то как?

Дмитрий Зайцев

Есть один нюанс, связанный с работой данного функционала: если компьютер пользователя  включен в состав домена, то данный функционал не отрабатывает. На компьютере пользователя, не включенном в состав домена Windows данный функционал работает на 100% корректно. 

Пока в процессе решения вопрос...

 

 

Дмитрий Зайцев

Дополнение: для корректной работы данного функционала необходимо наличие соответствующего ПО.

  1. MSSoap
  2. При использовании службы преобразования для формирования pdf желательно установить приложение MSOffice на компьютере с установленной службой.
  3. На рабочем месте делопроизводителя, который будет проставлять штампы на документ необходимо установить криптопровайдер. В противной случае функционал не сможет считать  данные цифровой подписи, которой подписан документ. 

 

Савин Вячеслав

При обращении Certificate.SubjectName из сертификата вытаскивается то, что у него прописано в поле subject CN. Это прекрасно работает с нашими локальными сертификатами, т.к. у нас там прописывается ФИО владельца. Но с сертификатами выданными на организацию сторонними центрами в CN значится название организации, а фамилия владельца идет в G и имя (или имя и отчество) в SN. Т.е. в поле subject не просто CN = Вася Пупкин, а CN = ООО "Рога и Копыта" G = Вася SN = Пупкин.

Есть ли возможность обращаться к произвольным параметрам поля subject?

Елена Питомцева

Вячеслав Савин, рекомендую задать отдельный вопрос в разделе Вопросов и сослаться на эту статью, если вы делаете по рекомендациям из нее. Так он попадет в рассылку и больше участников его увидит и подключится к ответу. Не забудьте поставить теги - Разработка и Электронная подпись, тогда быстрее подключатся те, кто на них подписаны. 

Авторизуйтесь, чтобы написать комментарий