Всем привет. Эта статья будет полезна тем, кто столкнулся с проблемой проверок доверенностей при работе с электронным документооборотом через СБИС и Диадок.  Речь идет не о МЧД (машиночитаемой доверенности), а о проверке обычных бумажных доверок.

Так же возможно кому то просто будет полезно почерпнуть принципы работы через API.

Ко мне эта задача прилетела от юристов, нашей компании, которые постоянно проверяли документы вручную. (смотрели вручную кем подписан документ и потом искали эту доверенность в сканах.

1. Первое что нам понадобится это реестр подписантов контрагентов. Формируется в полу автоматическом режиме, автоматом подгружается: ФИО, должность, название компании, ИНН. Далее вручную заполняются поля: дата истечения доверенности, номер доверенности, ФИО и почта ответственного за контрагента, а также ФИО и почта руководителя ответственного.

2. Реестр прочитанных документов, по которым еще не завершился документооборот. Это необходимо что бы не запускать каждый раз программу на большие сроки сканирования документов. (По умолчанию я запускаю скрипт, читающий вчерашнюю дату) если нужен другой период — это возможно указать при вызове скрипта.  Реестр незавершенных документов хранит только два значения. Идентификатор документа и его состояние.

Для решения поставленной задачи использовал API сервисов СБИС и Диадок.

Весь код написан на PowerShell.

Отдельно разобью описание для каждого их сервисов.

СБИС

1. Самое первое что необходимо сделать это пройти авторизацию на сервисе.

API сбиса принимает все запросы в формате JSON что бы не конвертировать массив в JSON  я сразу пишу переменные в формате JSON.


$url = "https://online.sbis.ru/auth/service/" #Путь до авторизации в API СБИС
$urlquery = "https://online.sbis.ru/service/?srv=1" 


#Авторизацию проходим по логину и паролю.
$Body = '{
    "jsonrpc":"2.0",
    "method":"СБИС.Аутентифицировать",
    "params" :{
       "Параметр":{
          "Логин":"API_login",
          "Пароль":" API_Password"
       }
    },
    "id":"0"
 }'
# на основе этих данных получаем токен он нужен будет нам для дальнейших запросов

$token = (Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $url -Body $Body).result 
 
# вставляем эти данные в заголовок будущих запросов

$headers = @{
    'X-SBISSessionID' = $token
} 

2. Загружаем в переменную реестр доверенностей

$pathxlsx = "E:\Scripts\ChekSign\Доверенности.xlsx" 
$dataexcel = Import-Excel -Path $pathxlsx 

3. Проверяем реестр ранее незавершенных документов, если у них изменилось состояние на “завершено” то проваливаемся вглубь документа, в противном случае просто заново записываем эти данные в реестр незавершенных сообщений (реестр перезаписывается каждый запуск программы, что бы не удалять построчно из экселя).

Внутри пакета документов нас интересует документ с названием “Уведомление о приеме”.  А что бы получить именно подписанта (того чьей эцп был подписан документ,   а не промежуточных лиц) нужно вычленять вложение  которые содержит слово титул(таких вложений может быть много, но нам нужно самое первое с индексом 0.

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

Если кратко нужный нам сертификат передается по следующему пути: Документ/событие(уведомление о приеме)/вложение Название:(Передаточный документ (титул покупателя))/Подпись/сертификат/ФИО. Получаем это через метод СБИС.ПрочитатьДокумент

$urlnofinish="E:\Scripts\ChekSign\nofinishsbis.xlsx"  
#Создаем массивы куда будем заносить номера и статусы тех документов, которые не прошли проверку, в том числе повторно. 
$arr_nofinish_id = @()
$arr_nofinish_status = @() 
$isfile = Test-Path $urlnofinish #если файл существует считываем из него данные.
if ($isfile){
$nofinish = Import-Excel -Path $urlnofinish
foreach ($nf in $nofinish){ 

$JsonBodyNoFinish =  '{
   "jsonrpc": "2.0",
   "method": "СБИС.ПрочитатьДокумент",
   "params": {
      "Документ": {
         "Идентификатор": "'+$nf.Идентификатор+'",
         "ДопПоля": "ДополнительныеПоля"
      }
   },
   "id": 0
}'




$ArrNames =  Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $urlquery -Body $JsonBodyNoFinish -Headers $headers

$inb = $ArrNames.result.Событие
$i=0

if (($ArrNames.result.Состояние.Название -ne "Выполнение завершено успешно")  -and ($ArrNames.result.Состояние.Название -ne "Выполнение завершено с проблемами")) {
$arr_nofinish_id += $ArrNames.result.Идентификатор
$arr_nofinish_status += $ArrNames.result.Состояние.Название
}
else {

foreach ($in in $inb){

if ($in.Название -eq "Уведомление о приеме"){
$tin = $in.Вложение.Название
$i=0
foreach ($t in $tin){
if ($t.Contains("титул")){

foreach ($excel in $dataexcel) {
$in.Вложение.Подпись.Сертификат.ИНН[$i]
$in.Вложение.Подпись.Сертификат.Название[$i]
$in.Вложение.Подпись.Сертификат.ФИО[$i]
$in.Вложение.Подпись.Сертификат.Должность[$i]


if ($excel.ФИО -eq $in.Вложение.Подпись.Сертификат.ФИО[$i]) {
$f = 1
if ($excel.Дата -eq $null){

}
else {
if($excel.Доверенность -ne "Устав"){
if ($date -gt $excel.Дата_истечения_доверенности){


if($arr_data_name -notcontains $in.Вложение.Подпись.Сертификат.ФИО[$i]) {
$arr_data_name +=($in.Вложение.Подпись.Сертификат.ФИО[$i])
$arr_data_company +=($in.Вложение.Подпись.Сертификат.Название[$i])
$arr_data_master +=($excel.Отвественный)
$arr_data_email+=($excel.Email)
$arr_data_position +=($excel.Должность)

}
}
}
}
}

}

if ($f -eq 0 ){



if ( $arr_name -notcontains $in.Вложение.Подпись.Сертификат.ФИО[$i] ) {

$arr_name+=($in.Вложение.Подпись.Сертификат.ФИО[$i])
if ($in.Вложение.Подпись.Сертификат.ИНН[$i] -ne $null){
if ($in.Вложение.Подпись.Сертификат.Название[$i] -ne "") {
$arr_company+=($in.Вложение.Подпись.Сертификат.Название[$i])
$arr_position+=($in.Вложение.Подпись.Сертификат.Должность[$i])
}

if ($in.Вложение.Подпись.Сертификат.Название[$i] -eq ""){
$arr_company+= ($in.Вложение.Подпись.Сертификат.Название[$i])
$arr_position+=($in.Вложение.Подпись.Сертификат.Должность[$i])
} 
}
else
{
$arr_company+=($in.Вложение.Подпись.Сертификат.ФИО[$i])
$arr_inn+=($in.Вложение.Подпись.Сертификат.ИНН[$i])
}

}

}

}
$i++
}
}
}


} 
else{
$Null | Export-Excel -Path $urlnofinish  -WorksheetName "Лист1"   -AutoSize  
$book = Open-ExcelPackage -Path $urlnofinish
$worksheet = $book.Workbook.Worksheets['Лист1']

$worksheet.Cells[1,1].Value = "Идентификатор"
$worksheet.Cells[1,2].Value = "Состояние"

Close-ExcelPackage $book

4. После того как прочитали старые документы переходим к чтению новых.

Сперва полаем список документов, а далее обращаемся к каждому документу напрямую.

Сразу хочу отметить что при обращении к списку документов чтение происходит постранично, и на странице влазит не более 200 документов.

По-этому читаем постранично и заносим все в массив документов. 

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

В данном примере write – host $msg  это как раз оповещения и переменную $msg нужно передать в процедуру отправки почты (см ниже)

Так же хочу отметить если должность у подписанта директор, ген директор, президент то не проверяем доверенность ибо она не нужна.

$dStart = (((date).Day - 1).ToString() + "." + ((date).Month).ToString() + "." +((date).Year).ToString()) 

$dEnd = (((date).Day - 1).ToString() + "." + ((date).Month).ToString() + "." +((date).Year).ToString()) 

$flag = 0 
$fl =0 
$arr_name = @()
$arr_company = @()
$arr_inn = @()
$arr_kpp = @()
$arr_position = @()

$arr_data_name = @()
$arr_data_company = @()
$arr_data_master = @()
$arr_data_email = @()
$arr_data_position = @() 
$s = $dStart
$po= $dEnd 



$JsonBodyQuery2 = '{

   "jsonrpc": "2.0",
   "method": "СБИС.СписокДокументов",
   "params": {
      "Фильтр": {
         "ДатаС": "'+$s+'",
		 "ДатаПо": "'+$po+'",
		 "Направление": "Исходящий",
         "Тип": "ДокОтгрИсх",
		 "Навигация": {
        "РазмерСтраницы": "'+$itempagecount+'",
        "Страница" : "'+$page+'"
		}
      }
   },
   "id": 0


}'


$i=0



#получаем список документов и обрщаемся к каждому по айди

$Docs =  Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $urlquery -Body $JsonBodyquery2 -Headers $headers


while ($flag -eq 0) {


$Ids = $Docs.result.Документ



foreach ($id in $Ids) {

$JsonBodyQuery4 =  '{
   "jsonrpc": "2.0",
   "method": "СБИС.ПрочитатьДокумент",
   "params": {
      "Документ": {
         "Идентификатор": "'+ $id.Идентификатор+ '",
         "ДопПоля": "ДополнительныеПоля"
      }
   },
   "id": 0
}'
#проверяем подписи
if (($id.Состояние.Название -ne "Выполнение завершено успешно")  -and ($id.Состояние.Название -ne "Выполнение завершено с проблемами")) {
if ($arr_nofinish_id -notcontains $id.Идентификатор){
$arr_nofinish_id += $id.Идентификатор
$arr_nofinish_status += $id.Состояние.Название
}
}

else {

$ArrNames =  Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $urlquery -Body $JsonBodyquery4 -Headers $headers

$inboxes =  $ArrNames.result.Событие

foreach ( $inbox in $inboxes){


if ($inbox.Название -eq "Уведомление о приеме"   ){
$tinboxes = $inbox.Вложение.Название
$i=0

foreach ($tinbox in $tinboxes ){
if ($tinbox.Contains("титул")){


if ($inbox.Вложение.Подпись.Сертификат.Название.Count -eq 1) {

$invlpodsertnaz = $inbox.Вложение.Подпись.Сертификат.Название
$invlpodsertfio = $inbox.Вложение.Подпись.Сертификат.ФИО
$invlpodsertdol = $inbox.Вложение.Подпись.Сертификат.Должность

}
else{
$invlpodsertnaz = $inbox.Вложение.Подпись.Сертификат.Название[$i]
$invlpodsertfio = $inbox.Вложение.Подпись.Сертификат.ФИО[$i]
$invlpodsertdol = $inbox.Вложение.Подпись.Сертификат.Должность[$i]
}
$Namestring = ($invlpodsertnaz).ToUpper()
if ($invlpodsertnaz -ne 'СОБСТВЕННАЯ ФИРМА’) { #тут убираем собственную фирму что бы # не проверять своих подпсиантов(по умолчанию считаем что у них ест доверенности
$f = 0 
foreach ($excel in $dataexcel) {

if ($excel.ФИО -eq $invlpodsertfio) {
$f = 1
if ($excel.Дата -eq $null){

}
else {
if($excel.Доверенность -ne "Устав"){
if ($date -gt $excel.Дата_истечения_доверенности){


if($arr_data_name -notcontains $invlpodsertfio) {
$arr_data_name +=($invlpodsertfio)
$arr_data_company +=($invlpodsertnaz)
$arr_data_master +=($excel.Отвественный)
$arr_data_email+=($excel.Email)
$arr_data_position +=($excel.Должность)

}

}
}
}
}}

if ($f -eq 0 ){



if ( $arr_name -notcontains $invlpodsertfio) {

$arr_name+=($invlpodsertfio)
if ($id.Контрагент.СвЮЛ.ИНН -ne $null){
if ($invlpodsertnaz -ne "") {
$arr_company+=($invlpodsertnaz)
$arr_position+=($invlpodsertdol)
}
if ($invlpodsertnaz -eq ""){
$arr_company+= ($id.Контрагент.СвЮЛ.Название)
$arr_position+=($invlpodsertdol)
}
$arr_inn+=($id.Контрагент.СвЮЛ.ИНН)
}
else
{
$arr_company+=($id.Контрагент.СвФЛ.Фамилия + " "+ $id.Контрагент.СвФЛ.Имя + " " + $id.Контрагент.СвФЛ.Отчество )
$arr_inn+=($id.Контрагент.СвФЛ.ИНН)
}

}


}


}

}
$i++
}
}

}






}
}




$page+=1 
$JsonBodyQuery2 = '{

   "jsonrpc": "2.0",
   "method": "СБИС.СписокДокументов",
   "params": {
      "Фильтр": {
         "ДатаС": "'+$s+'",
		 "ДатаПо": "'+$po+'",
		 "Направление": "Исходящий",
         "Тип": "ДокОтгрИсх",
		 "Навигация": {
        "РазмерСтраницы": "'+$itempagecount+'",
        "Страница" : "'+$page+'"
		}
      }
   },
   "id": 0


}'

$Docs =  Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $urlquery -Body $JsonBodyquery2 -Headers $headers

if ($Docs.result.Навигация.ЕстьЕще -ne "Да") {$fl+=1}
if ($fl -gt 1) {$flag=1}


}


Remove-Item -Path $urlnofinish
$Null | Export-Excel -Path $urlnofinish  -WorksheetName "Лист1"   -AutoSize 
 
$book = Open-ExcelPackage -Path $urlnofinish
$worksheet = $book.Workbook.Worksheets['Лист1']


$worksheet.Cells[1,1].Value = "Идентификатор"
$worksheet.Cells[1,2].Value = "Состояние"
$i=0

for ($i=0; $i -lt $arr_nofinish_id.count; $i++ ){
$worksheet.Cells[($i+2),1].Value = $arr_nofinish_id[$i]
$worksheet.Cells[($i+2),2].Value = $arr_nofinish_status[$i]


}
Close-ExcelPackage $book 

if ($arr_name -ne $null){

$book = Open-ExcelPackage -Path $pathxlsx
$worksheet = $book.Workbook.Worksheets['Лист1']
$i = 0 
$j = 0 

$msg="Доверенности не найдены, необходимо добавить ответственных для:`n "
for ($i = 0; $i -lt ($arr_name.Count); $i++ ){
$worksheet.Cells[($dataexcel.Count+2+$i),1].Value = $arr_name[$i]
$worksheet.Cells[($dataexcel.Count+2+$i),2].Value = $arr_company[$i]
$worksheet.Cells[($dataexcel.Count+2+$i),3].Value = $arr_position[$i]
$worksheet.Cells[($dataexcel.Count+2+$i),4].Value = $arr_inn[$i]
$msg+=$arr_name[$i]+ " компания " + $arr_company[$i] +" должность "+ $arr_position[$i] +" ИНН " + $arr_inn[$i]  +"`n"
}
Close-ExcelPackage $book 

Write-Host $msg
}


$i = 0 
$j = 0


$arr_unic_data_email =@()

for($i=0;$i -le ($arr_data_email.Count-1); $i++){
if ($arr_unic_data_email -notcontains $arr_data_email[$i] ){
$arr_unic_data_email += ($arr_data_email[$i])
}
}



$msg =""
for($j=0;$j -le ($arr_unic_data_email.Count-1); $j++){
$msg ="Дата доверенностей истекла для:`n"
for($i=0;$i -le $arr_data_name.Count; $i++){
if ($arr_unic_data_email[$j] -eq $arr_data_email[$i]) {
$msg += $arr_data_name[$i] +" компания "+$arr_data_company[$i] +" должность " + $arr_data_position[$i] +" Отвественный "+ $arr_data_master[$i] +"`n"
}
}
Write-Host "Письмо для"$arr_unic_data_email[$j]"`n"$msg
}

$dataexcel = Import-Excel -Path $pathxlsx
$i=0
$book = Open-ExcelPackage -Path $pathxlsx
$worksheet = $book.Workbook.Worksheets['Лист1']
for ($i=2; $i -lt $dataexcel.Count; $i++){

if ($worksheet.Cells[$i,3].Value -ne ""){
$str = (($worksheet.Cells[$i,3].Value)).ToUpper()
if (($str -eq "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР") -or ($str -eq "ПРЕЗИДЕНТ") -or ($str -eq "ДИРЕКТОР")){
$worksheet.Cells[$i,5].Value = "Устав" 
}
}
}

Close-ExcelPackage $book 



Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $url -Body $JsonBody_close -Headers $headers 

5. Модуль отправки почты

function SendMailToUser($To,$message) {
$From="notifier@mydomain.ru"
$Subject="Проверка сертификатов"
$Body=$message
$Password="Pa$$w0rd"
$SecPassword=New-Object -TypeName System.Security.SecureString
$Password.ToCharArray() | foreach {$SecPassword.AppendChar($_)}
$Credintial=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $From,$SecPassword
$smtpServer="mail.mydomain.ru"
$SMTPport="25"
$encoding = [System.Text.Encoding]::UTF8
Send-MailMessage -From $From -To $To -Subject $Subject -BodyAsHtml -Body $Body -Credential $Credintial -SmtpServer $smtpServer -Port $SMTPport -Priority "High"  -Encoding $encoding  -ErrorAction Stop
} 

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

function ChekSbis{
[CmdletBinding()]
   param(
   $dStart = (((date).Day - 1).ToString() + "." + ((date).Month).ToString() + "." +((date).Year).ToString()),
 
   $dEnd = (((date).Day - 1).ToString() + "." + ((date).Month).ToString() + "." +((date).Year).ToString())


   )
$url = "https://online.sbis.ru/auth/service/"
$urlquery = "https://online.sbis.ru/service/?srv=1"
$pathxlsx = "E:\Scripts\ChekSign\Доверенности.xlsx"
$s = $dStart
$po= $dEnd

$dataexcel = Import-Excel -Path $pathxlsx
$flag = 0 
$fl =0 
$arr_name = @()
$arr_company = @()
$arr_inn = @()
$arr_kpp = @()
$arr_position = @()

$arr_data_name = @()
$arr_data_company = @()
$arr_data_master = @()
$arr_data_email = @()
$arr_data_position = @()

#Тело запроса для подключения к апи сбиса

$Body = '{
    "jsonrpc":"2.0",
    "method":"СБИС.Аутентифицировать",
    "params" :{
       "Параметр":{
          "Логин":"API_login",
          "Пароль":"API_Password"
       }
    },
    "id":"0"
 }'
$JsonBody = $Body 

$token = (Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $url -Body $JsonBody).result
$Body_close = '{
    "jsonrpc":"2.0",
    "method":"СБИС.Выход",
    "params" :{},
    "id":"0"
 }'
 $JsonBody_close = $Body_close

$headers = @{
    'X-SBISSessionID' = $token
}


$date = date

$page = 0 
$itempagecount = 200
$urlnofinish="E:\Scripts\ChekSign\nofinishsbis.xlsx" 
$arr_nofinish_id = @()
$arr_nofinish_status = @()
$arr_data_nofinish_id = @()
$arr_data_nofinish_status = @()
$isfile = Test-Path $urlnofinish
#проверка ранее не подписанных идентефикаторов 
if ($isfile){
$nofinish = Import-Excel -Path $urlnofinish
foreach ($nf in $nofinish){ 

$JsonBodyNoFinish =  '{
   "jsonrpc": "2.0",
   "method": "СБИС.ПрочитатьДокумент",
   "params": {
      "Документ": {
         "Идентификатор": "'+$nf.Идентификатор+'",
         "ДопПоля": "ДополнительныеПоля"
      }
   },
   "id": 0
}'



$ArrNames =  Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $urlquery -Body $JsonBodyNoFinish -Headers $headers

$inb = $ArrNames.result.Событие
$i=0

if (($ArrNames.result.Состояние.Название -ne "Выполнение завершено успешно")  -and ($ArrNames.result.Состояние.Название -ne "Выполнение завершено с проблемами")) {
$arr_nofinish_id += $ArrNames.result.Идентификатор
$arr_nofinish_status += $ArrNames.result.Состояние.Название
}
else {

foreach ($in in $inb){

if ($in.Название -eq "Уведомление о приеме"){
$tin = $in.Вложение.Название
$i=0
foreach ($t in $tin){
if ($t.Contains("титул")){

foreach ($excel in $dataexcel) {
$in.Вложение.Подпись.Сертификат.ИНН[$i]
$in.Вложение.Подпись.Сертификат.Название[$i]
$in.Вложение.Подпись.Сертификат.ФИО[$i]
$in.Вложение.Подпись.Сертификат.Должность[$i]


if ($excel.ФИО -eq $in.Вложение.Подпись.Сертификат.ФИО[$i]) {
$f = 1
if ($excel.Дата -eq $null){

}
else {
if($excel.Доверенность -ne "Устав"){
if ($date -gt $excel.Дата_истечения_доверенности){


if($arr_data_name -notcontains $in.Вложение.Подпись.Сертификат.ФИО[$i]) {
$arr_data_name +=($in.Вложение.Подпись.Сертификат.ФИО[$i])
$arr_data_company +=($in.Вложение.Подпись.Сертификат.Название[$i])
$arr_data_master +=($excel.Отвественный)
$arr_data_email+=($excel.Email)
$arr_data_position +=($excel.Должность)

}



}
}
}
}

}

if ($f -eq 0 ){




if ( $arr_name -notcontains $in.Вложение.Подпись.Сертификат.ФИО[$i] ) {

$arr_name+=($in.Вложение.Подпись.Сертификат.ФИО[$i])
if ($in.Вложение.Подпись.Сертификат.ИНН[$i] -ne $null){
if ($in.Вложение.Подпись.Сертификат.Название[$i] -ne "") {
$arr_company+=($in.Вложение.Подпись.Сертификат.Название[$i])
$arr_position+=($in.Вложение.Подпись.Сертификат.Должность[$i])
}

if ($in.Вложение.Подпись.Сертификат.Название[$i] -eq ""){
$arr_company+= ($in.Вложение.Подпись.Сертификат.Название[$i])
$arr_position+=($in.Вложение.Подпись.Сертификат.Должность[$i])
} 
 
$arr_inn+=($in.Вложение.Подпись.Сертификат.ИНН[$i])

}
else
{
$arr_company+=($in.Вложение.Подпись.Сертификат.ФИО[$i])
$arr_inn+=($in.Вложение.Подпись.Сертификат.ИНН[$i])

}

}


}




}
$i++
}
}
}


}
}

}
#если реестра ранее не подписанных идентефикаторов не существует создаем его
else{
$Null | Export-Excel -Path $urlnofinish  -WorksheetName "Лист1"   -AutoSize  
$book = Open-ExcelPackage -Path $urlnofinish
$worksheet = $book.Workbook.Worksheets['Лист1']

$worksheet.Cells[1,1].Value = "Идентификатор"
$worksheet.Cells[1,2].Value = "Состояние"

Close-ExcelPackage $book 

}








$JsonBodyQuery2 = '{

   "jsonrpc": "2.0",
   "method": "СБИС.СписокДокументов",
   "params": {
      "Фильтр": {
         "ДатаС": "'+$s+'",
		 "ДатаПо": "'+$po+'",
		 "Направление": "Исходящий",
         "Тип": "ДокОтгрИсх",
		 "Навигация": {
        "РазмерСтраницы": "'+$itempagecount+'",
        "Страница" : "'+$page+'"
		}
      }
   },
   "id": 0


}'



$i=0




$Docs =  Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $urlquery -Body $JsonBodyquery2 -Headers $headers


while ($flag -eq 0) {


$Ids = $Docs.result.Документ




foreach ($id in $Ids) {

$JsonBodyQuery4 =  '{
   "jsonrpc": "2.0",
   "method": "СБИС.ПрочитатьДокумент",
   "params": {
      "Документ": {
         "Идентификатор": "'+ $id.Идентификатор+ '",
         "ДопПоля": "ДополнительныеПоля"
      }
   },
   "id": 0
}'
#проверяем подписи
if (($id.Состояние.Название -ne "Выполнение завершено успешно")  -and ($id.Состояние.Название -ne "Выполнение завершено с проблемами")) {
if ($arr_nofinish_id -notcontains $id.Идентификатор){
$arr_nofinish_id += $id.Идентификатор
$arr_nofinish_status += $id.Состояние.Название
}
}

else {


$ArrNames =  Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $urlquery -Body $JsonBodyquery4 -Headers $headers


$inboxes =  $ArrNames.result.Событие

foreach ( $inbox in $inboxes){


if ($inbox.Название -eq "Уведомление о приеме"   ){
$tinboxes = $inbox.Вложение.Название
$i=0

foreach ($tinbox in $tinboxes ){
if ($tinbox.Contains("титул")){



if ($inbox.Вложение.Подпись.Сертификат.Название.Count -eq 1) {

$invlpodsertnaz = $inbox.Вложение.Подпись.Сертификат.Название
$invlpodsertfio = $inbox.Вложение.Подпись.Сертификат.ФИО
$invlpodsertdol = $inbox.Вложение.Подпись.Сертификат.Должность

}
else{
$invlpodsertnaz = $inbox.Вложение.Подпись.Сертификат.Название[$i]
$invlpodsertfio = $inbox.Вложение.Подпись.Сертификат.ФИО[$i]
$invlpodsertdol = $inbox.Вложение.Подпись.Сертификат.Должность[$i]
}
$Namestring = ($invlpodsertnaz).ToUpper()

if ($invlpodsertnaz -ne 'СОБСТВЕННАЯ ФИРМА'){
$f = 0 

foreach ($excel in $dataexcel) {

if ($excel.ФИО -eq $invlpodsertfio) {
$f = 1
if ($excel.Дата -eq $null){

}
else {
if($excel.Доверенность -ne "Устав"){
if ($date -gt $excel.Дата_истечения_доверенности){

#Write-Host Доверенность $excel.ФИО  истекла или не установлена дата истечения

if($arr_data_name -notcontains $invlpodsertfio) {
$arr_data_name +=($invlpodsertfio)
$arr_data_company +=($invlpodsertnaz)
$arr_data_master +=($excel.Отвественный)
$arr_data_email+=($excel.Email)
$arr_data_position +=($excel.Должность)

}

}
}
}
}}

if ($f -eq 0 ){




if ( $arr_name -notcontains $invlpodsertfio) {

$arr_name+=($invlpodsertfio)
if ($id.Контрагент.СвЮЛ.ИНН -ne $null){
if ($invlpodsertnaz -ne "") {
$arr_company+=($invlpodsertnaz)
$arr_position+=($invlpodsertdol)
}
if ($invlpodsertnaz -eq ""){
$arr_company+= ($id.Контрагент.СвЮЛ.Название)
$arr_position+=($invlpodsertdol)
}

$arr_inn+=($id.Контрагент.СвЮЛ.ИНН)

}
else
{
$arr_company+=($id.Контрагент.СвФЛ.Фамилия + " "+ $id.Контрагент.СвФЛ.Имя + " " + $id.Контрагент.СвФЛ.Отчество )

$arr_inn+=($id.Контрагент.СвФЛ.ИНН)

}

}


}


}

}
$i++
}
}

}






}
}
<##>



$page+=1 
$JsonBodyQuery2 = '{

   "jsonrpc": "2.0",
   "method": "СБИС.СписокДокументов",
   "params": {
      "Фильтр": {
         "ДатаС": "'+$s+'",
		 "ДатаПо": "'+$po+'",
		 "Направление": "Исходящий",
         "Тип": "ДокОтгрИсх",
		 "Навигация": {
        "РазмерСтраницы": "'+$itempagecount+'",
        "Страница" : "'+$page+'"
		}
      }
   },
   "id": 0


}'

$Docs =  Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $urlquery -Body $JsonBodyquery2 -Headers $headers

if ($Docs.result.Навигация.ЕстьЕще -ne "Да") {$fl+=1}
if ($fl -gt 1) {$flag=1}


}


Remove-Item -Path $urlnofinish
$Null | Export-Excel -Path $urlnofinish  -WorksheetName "Лист1"   -AutoSize 
 
$book = Open-ExcelPackage -Path $urlnofinish
$worksheet = $book.Workbook.Worksheets['Лист1']


$worksheet.Cells[1,1].Value = "Идентификатор"
$worksheet.Cells[1,2].Value = "Состояние"
$i=0

for ($i=0; $i -lt $arr_nofinish_id.count; $i++ ){

$worksheet.Cells[($i+2),1].Value = $arr_nofinish_id[$i]
$worksheet.Cells[($i+2),2].Value = $arr_nofinish_status[$i]


}
Close-ExcelPackage $book 


if ($arr_name -ne $null){

$book = Open-ExcelPackage -Path $pathxlsx
$worksheet = $book.Workbook.Worksheets['Лист1']
$i = 0 
$j = 0 

$msg="Доверенности не найдены, необходимо добавить ответственных для:`n "
for ($i = 0; $i -lt ($arr_name.Count); $i++ ){
$worksheet.Cells[($dataexcel.Count+2+$i),1].Value = $arr_name[$i]
$worksheet.Cells[($dataexcel.Count+2+$i),2].Value = $arr_company[$i]
$worksheet.Cells[($dataexcel.Count+2+$i),3].Value = $arr_position[$i]
$worksheet.Cells[($dataexcel.Count+2+$i),4].Value = $arr_inn[$i]

$msg+=$arr_name[$i]+ " компания " + $arr_company[$i] +" должность "+ $arr_position[$i] +" ИНН " + $arr_inn[$i]  +"`n"
}
Close-ExcelPackage $book 

Write-Host $msg
}


$i = 0 
$j = 0


$arr_unic_data_email =@()

for($i=0;$i -le ($arr_data_email.Count-1); $i++){
if ($arr_unic_data_email -notcontains $arr_data_email[$i] ){
$arr_unic_data_email += ($arr_data_email[$i])
}
}



$msg =""
for($j=0;$j -le ($arr_unic_data_email.Count-1); $j++){
$msg ="Дата доверенностей истекла для:`n"
for($i=0;$i -le $arr_data_name.Count; $i++){
if ($arr_unic_data_email[$j] -eq $arr_data_email[$i]) {
$msg += $arr_data_name[$i] +" компания "+$arr_data_company[$i] +" должность " + $arr_data_position[$i] +" Отвественный "+ $arr_data_master[$i] +"`n"
}
}
Write-Host "Письмо для"$arr_unic_data_email[$j]"`n"$msg
}

$dataexcel = Import-Excel -Path $pathxlsx
$i=0
$book = Open-ExcelPackage -Path $pathxlsx
$worksheet = $book.Workbook.Worksheets['Лист1']
for ($i=2; $i -lt $dataexcel.Count; $i++){
#Write-Host $i ----- $worksheet.Cells[$i,3].Value
if ($worksheet.Cells[$i,3].Value -ne ""){
$str = (($worksheet.Cells[$i,3].Value)).ToUpper()
if (($str -eq "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР") -or ($str -eq "ПРЕЗИДЕНТ") -or ($str -eq "ДИРЕКТОР")){
$worksheet.Cells[$i,5].Value = "Устав" 
}
}
}

Close-ExcelPackage $book 




Invoke-RestMethod -Method Post -ContentType "application/json-rpc;charset=utf-8" -Uri $url -Body $JsonBody_close -Headers $headers
}


ChekSbis -dStart "10.01.2023" -dEnd "16.06.2023" # для запуска для периода
#ChekSbis  запуск по умолчанию за вчера

Диадок

Логика примерно такая же, только ключ разработчика для обращения к документам диадока стоит денег в год. И авторизация немного другой вид имеет.   По-этому выложу просто код целиком без пояснений.

function ChekKontur{
[CmdletBinding()]
   param(
   $dStart = (((date).Day - 1).ToString() + "." + ((date).Month).ToString() + "." +((date).Year).ToString()),
 
   $dEnd = (((date).Day - 1).ToString() + "." + ((date).Month).ToString() + "." +((date).Year).ToString())
   
   )

$url = "https://diadoc-api.kontur.ru/v3/Authenticate?type=password"
$docc = 100
$Docs = @()
$pathxlsx = "C:\Bin\Scripts\ChekSign\Доверенности.xlsx"
$pathnofinish  = "C:\Bin\Scripts\ChekSign\NoFinish.xlsx"
$s = $dStart
$po= $dEnd
$docstatus= "Any.OutboundNotRevoked"
$dataexcel = Import-Excel -Path $pathxlsx
$date = date
$arr_name = @()
$arr_company = @()
$arr_inn = @()
$arr_kpp = @()
$arr_data_name = @()
$arr_data_company = @()
$arr_data_master = @()
$arr_data_email = @()
$arr_nofinish_idmessage = @()
$arr_nofinish_entityId  = @()
$arr_nofinish_status = @()
$arr_check_nofinish_idmessage = @()
$arr_check_nofinish_entityId  = @()
$arr_check_nofinish_status = @()
$arr_nodate = @{}
$arr_data_position = @()
$arr_position = @()
$arr_data_title  =@()










$Header =@{
"Authorization" = "DiadocAuth ddauth_api_client_id=API-ключ"
"ContentLength"= "1252"
"Content-Type"= "application/json"
}


 $Body = '{
"login": "api_логин",
"password": "пароль"
}'
$token2 = Invoke-RestMethod -Method Post -Uri $url -Headers $Header -Body $Body 
$auth = "DiadocAuth ddauth_api_client_id=API-ключ,ddauth_token=" +$token2
$url2="https://diadoc-api.kontur.ru/GetMyOrganizations"

$Header2 =@{
"Authorization" = $auth
"ContentLength"= "1252"
"Content-Type"= "application/json"
}

$Header5 = @{
"Authorization" = $auth
"ContentLength"= "1252"
"Content-Type"= "application/json"
}



$Box = Invoke-RestMethod  -Uri $url2 -Headers $Header2 -Method GET 

$BoxID =  $Box.Organizations.Boxes.BoxId
$OrigId = $Box.Organizations.OrgId

$url3="https://diadoc-api.kontur.ru/v3/GetDocuments"

 $Body2 = @{
 "boxid" = $BoxID
 "filterCategory"=$docstatus
 "fromDocumentDate"=$s
 "toDocumentDate"=$po
 "count"= $docc
}

$doc = Invoke-RestMethod  -Uri $url3 -Headers $Header2 -Body $Body2 -Method GET 
$doctotal = $doc.TotalCount
Write-Host Documentov ---------------------------------------------------------- $doc.TotalCount
$doccount = $doc.Documents.Count
$i=1

$Docs += $doc.Documents

$docchangetotal = $doctotal

while ($doccount -lt $doctotal){
$i++
$docchangetotal = $doctotal - $docc
if ($docchangetotal -lt $docc) {$docc = $docchangetotal}

 $Body2 = @{
 "boxid" = $BoxID
 "filterCategory"=$docstatus
 "fromDocumentDate"=$s
 "toDocumentDate"=$po
 "count"=$docc
 "afterIndexKey" = $doc.Documents.IndexKey[-1]
 }
 $doc = Invoke-RestMethod  -Uri $url3 -Headers $Header2 -Body $Body2 -Method GET


 $doccount += $doc.Documents.Count
$Docs += $doc.Documents

}


#проверяем не подписанные элементы

$nofinish = $Null


$nofinish = Import-Excel -Path $pathnofinish


if ($nofinish -ne $Null){

Remove-Item -Path $pathnofinish

$Null | Export-Excel -Path $pathnofinish  -WorksheetName "Лист1"   -AutoSize  


$book = Open-ExcelPackage -Path $pathnofinish
$worksheet = $book.Workbook.Worksheets['Лист1']
$i = 0 
$j = 0

$worksheet.Cells[1,1].Value = "boxId"
$worksheet.Cells[1,2].Value = "MessageID"
$worksheet.Cells[1,3].Value = "entityId"
$worksheet.Cells[1,4].Value = "DocumentStatus"

$url10="https://diadoc-api.kontur.ru/V3/GetDocument"


foreach ($row in $nofinish){

 
  $Body10 = @{
 "boxId" = $row.boxId
 "entityId" = $row.entityId
 "messageId" = $row.MessageID
  }        
 

$check = Invoke-RestMethod  -Uri $url10 -Headers $Header2 -Body $Body10 -Method GET
#$check.UniversalTransferDocumentMetadata.DocumentStatus
if ($check.UniversalTransferDocumentMetadata.DocumentStatus -eq "OutboundWithRecipientSignature" ){


$url8="https://diadoc-api.kontur.ru/V5/GetMessage"
$url9="https://diadoc-api.kontur.ru/GetSignatureInfo"

$Header2 =@{
"Authorization" = $auth
"ContentLength"= "1252"
"Content-Type"= "application/json"
}

  $Body8 = @{
 "boxId" = $BoxID
 "messageId" = $row.messageid
 
 }              
 
$sertreq = Invoke-RestMethod  -Uri $url8 -Headers $Header2 -Body $Body8 -Method GET

$signs = $sertreq.Entities
ForEach ($sign in $signs){
if ($sign.EntityType -eq "Signature") {
$Body9 = @{
 "boxId" = $BoxID
 "messageId" =$row.messageid
 "entityId" = $sign.EntityId
  }
 $signdata = Invoke-RestMethod  -Uri $url9 -Headers $Header2 -Body $Body9 -Method GET


 if ($signdata.OrgInn -ne 'ИНН исключения') {
$f = 0 

foreach ($excel in $dataexcel) {
if ($excel.ФИО -eq ($signdata.Surname+" "+$signdata.FirstName)) {
$f = 1
if ($excel.Дата_истечения_доверенности -eq $null){
}
else {
if ($date -gt $excel.Дата_истечения_доверенности){


if($arr_data_name -notcontains ($signdata.Surname+" "+$signdata.FirstName)) {
$arr_data_name +=(($signdata.Surname+" "+$signdata.FirstName))
$arr_data_company +=($signdata.OrgName)
$arr_data_master +=($excel.Отвественный)
$arr_data_email+=($excel.Email)
$arr_data_position += ($excel.Должность)

}

}
}
}}


if ($f -eq 0 ){


if ( $arr_name -notcontains ($signdata.Surname+" "+$signdata.FirstName)) {

$arr_name+=(($signdata.Surname+" "+$signdata.FirstName))
$arr_company+= ($signdata.OrgName)
$arr_inn+=($signdata.OrgInn)
$arr_position+=($signdata.JobTitle)

}



}


}






  }

}

}
else {


$arr_check_nofinish_idmessage += $check.MessageID
$arr_check_nofinish_entityId += $check.entityId
$arr_check_nofinish_status += $check.UniversalTransferDocumentMetadata.DocumentStatus
}


}




if ($arr_check_nofinish_idmessage.Count -gt 1) {

for ($i=0; $i-le ($arr_check_nofinish_idmessage.Count-1); $i++){

$worksheet.Cells[($i+2),1].Value = $BoxID
$worksheet.Cells[($i+2),2].Value = $arr_check_nofinish_idmessage[$i]
$worksheet.Cells[($i+2),3].Value = $arr_check_nofinish_entityId[$i]
$worksheet.Cells[($i+2),4].Value = $arr_check_nofinish_status[$i]
}
}
Close-ExcelPackage $book 

}

$nofinish = $Null

$nofinish = Import-Excel -Path $pathnofinish



if ($nofinish -ne $null) {
foreach ($row in $nofinish){
$arr_nofinish_idmessage +=$row.MessageID
$arr_nofinish_entityId +=$row.entityId
$arr_nofinish_status +=$row.DocumentStatus
}

}

$i=1 


foreach ($message in $Docs) { 




if (($message.UniversalTransferDocumentMetadata.DocumentStatus -eq "OutboundWithRecipientSignature" ) -or ($message.UniversalCorrectionDocumentMetadata.DocumentStatus -eq "OutboundWithRecipientSignature" )){

$url8="https://diadoc-api.kontur.ru/V5/GetMessage"
$url9="https://diadoc-api.kontur.ru/GetSignatureInfo"

$Header2 =@{
"Authorization" = $auth
"ContentLength"= "1252"
"Content-Type"= "application/json"
}

  $Body8 = @{
 "boxId" = $BoxID
 "messageId" = $message.messageid
 
 }              
 
$sertreq = Invoke-RestMethod  -Uri $url8 -Headers $Header2 -Body $Body8 -Method GET

$signs = $sertreq.Entities
ForEach ($sign in $signs){
if ($sign.EntityType -eq "Signature") {
$Body9 = @{
 "boxId" = $BoxID
 "messageId" =$message.messageid
 "entityId" = $sign.EntityId
  }
 $signdata = Invoke-RestMethod  -Uri $url9 -Headers $Header2 -Body $Body9 -Method GET



 if ($signdata.OrgInn -ne 'ИНН исключения') {
$f = 0 

foreach ($excel in $dataexcel) {
if ($excel.ФИО -eq ($signdata.Surname+" "+$signdata.FirstName)) {

$f = 1
$changetitle = 0 
if (($excel.Должность -eq "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР") -or ($excel.Должность -eq "ПРЕЗИДЕНТ") -or ($excel.Должность -eq "ДИРЕКТОР")){
if (($signdata.JobTitle -ne "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР") -and ($signdata.JobTitle -ne "ПРЕЗИДЕНТ") -and ($signdata.JobTitle -ne "ДИРЕКТОР")){
$changetitle = 1
}

}

if ($excel.Дата_истечения_доверенности -eq $null){
}
else {
if($excel.Доверенность -ne "Устав"){
if ($date -gt $excel.Дата_истечения_доверенности){


if($arr_data_name -notcontains ($signdata.Surname+" "+$signdata.FirstName)) {
$arr_data_name +=(($signdata.Surname+" "+$signdata.FirstName))
$arr_data_company +=($signdata.OrgName)
$arr_data_master +=($excel.Отвественный)
$arr_data_email+=($excel.Email)
$arr_data_position+=($excel.Должность)
if ($changetitle -eq 1 ){
$arr_data_title += $signdata.JobTitle
}
else{
$arr_data_title += "NO"
}

}

}
}

}


}}


if ($f -eq 0 ){


if ( $arr_name -notcontains ($signdata.Surname+" "+$signdata.FirstName)) {

$arr_name+=(($signdata.Surname+" "+$signdata.FirstName))
$arr_company+= ($signdata.OrgName)
$arr_inn+=($signdata.OrgInn)
$arr_position+=($signdata.JobTitle)

}



}


}






  }

}


}
else {
if (($message.UniversalTransferDocumentMetadata.DocumentStatus -ne "OutboundRecipientSignatureRequestRejected") -or ($message.UniversalCorrectionDocumentMetadata.DocumentStatus -ne "OutboundRecipientSignatureRequestRejected" )){




if ($arr_check_nofinish_entityId -notcontains $message.EntityId  ){
$arr_nofinish_idmessage += $message.MessageId
$arr_nofinish_entityId  += $message.EntityId
if ($message.DocumentType -eq "UniversalCorrectionDocument") {
$arr_nofinish_status += $message.UniversalCorrectionDocumentMetadata.DocumentStatus
}
if ($message.DocumentType -eq "UniversalTransferDocument") {
$arr_nofinish_status += $message.UniversalTransferDocumentMetadata.DocumentStatus
}
}
}

}



}



Remove-Item -Path $pathnofinish

$Null | Export-Excel -Path $pathnofinish  -WorksheetName "Лист1"   -AutoSize  





$book = Open-ExcelPackage -Path $pathnofinish
$worksheet = $book.Workbook.Worksheets['Лист1']
$i = 0 
$j = 0

$worksheet.Cells[1,1].Value = "boxId"
$worksheet.Cells[1,2].Value = "MessageID"
$worksheet.Cells[1,3].Value = "entityId"
$worksheet.Cells[1,4].Value = "DocumentStatus"
if ($arr_nofinish_idmessage.Count -gt 1){
for ($i=0; $i-le ($arr_nofinish_idmessage.Count-1); $i++){

$worksheet.Cells[($i+2),1].Value = $BoxID
$worksheet.Cells[($i+2),2].Value = $arr_nofinish_idmessage[$i]
$worksheet.Cells[($i+2),3].Value = $arr_nofinish_entityId[$i]
$worksheet.Cells[($i+2),4].Value = $arr_nofinish_status[$i]
}
}
Close-ExcelPackage $book 

$arr_name


if ($arr_name -ne $null){

$book = Open-ExcelPackage -Path $pathxlsx
$worksheet = $book.Workbook.Worksheets['Лист1']
$i = 0 
$j = 0 

$msg="Доверенности не найдены, необходимо добавить ответственных для:`n <br /> "
for ($i = 0; $i -lt ($arr_name.Count); $i++ ){
$worksheet.Cells[($dataexcel.Count+2+$i),1].Value = $arr_name[$i]
$worksheet.Cells[($dataexcel.Count+2+$i),2].Value = $arr_company[$i]
$worksheet.Cells[($dataexcel.Count+2+$i),3].Value = $arr_position[$i]
$worksheet.Cells[($dataexcel.Count+2+$i),4].Value = $arr_inn[$i]
if (($arr_inn[$i] -eq "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР") -or ($arr_inn[$i] -eq "ПРЕЗИДЕНТ") -or ($arr_inn[$i] -eq "ДИРЕКТОР")){
$worksheet.Cells[($dataexcel.Count+2+$i),5].Value = "Устав" 
}
else{
$msg+=$arr_name[$i]+ " компания " + $arr_company[$i] +" должность "+ $arr_position[$i] +" ИНН " + $arr_inn[$i] +"`n <br />"
}
}
Close-ExcelPackage $book 

Write-Host $msg

}


$i = 0 
$j = 0


$arr_unic_data_email =@()

for($i=0;$i -le ($arr_data_email.Count-1); $i++){
if ($arr_unic_data_email -notcontains $arr_data_email[$i] ){
$arr_unic_data_email += ($arr_data_email[$i])
}
}



$msg =""
for($j=0;$j -le ($arr_unic_data_email.Count-1); $j++){
$msg ="Дата доверенностей истекла для:`n <br />"
for($i=0;$i -le $arr_data_name.Count; $i++){
if ($arr_unic_data_email[$j] -eq $arr_data_email[$i]) {

if ($arr_data_title[$i] -ne "NO"){
$msg +=$arr_data_name[$i] +" компания "+$arr_data_company[$i] + " должность  изменилась на: " + $arr_data_title[$i] +  "`n <br />"
}
else{
$msg += $arr_data_name[$i] +" компания "+$arr_data_company[$i] + " должность " + $arr_data_position[$i] +" Отвественный "+ $arr_data_master[$i] +"`n <br />"
}

}
}
Write-Host "Письмо для"$arr_unic_data_email[$j]  "`n" $msg

}

$dataexcel = Import-Excel -Path $pathxlsx
$i=0
$book = Open-ExcelPackage -Path $pathxlsx
$worksheet = $book.Workbook.Worksheets['Лист1']
for ($i=2; $i -lt $dataexcel.Count; $i++){
if ($worksheet.Cells[$i,3].Value -ne ""){
$str = ($worksheet.Cells[$i,3].Value).ToUpper()}
if (($str -eq "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР") -or ($str -eq "ПРЕЗИДЕНТ") -or ($str -eq "ДИРЕКТОР")){
$worksheet.Cells[$i,5].Value = "Устав" 
}

}
Close-ExcelPackage $book 

}

ChekKontur -dStart "01.01.2023" -dEnd "28.02.2023"

Комментарии (3)


  1. timka05
    19.06.2023 14:01

    Ну с учётом того, что не программист и задача решена - отлично!
    Хотя конечно PowerShell для таких задач - так себе ))


    1. walrus911 Автор
      19.06.2023 14:01

      Чем повершел плох для этой задачи?


      1. pfffffffffffff
        19.06.2023 14:01

        Синтаксис