Синтаксис и применение ОтборСообщенийСистемыВзаимодействия.По умолчанию в платформе 1С:Предприятие. Описание и примеры кода.
Синтаксис
Новый ОтборСообщенийСистемыВзаимодействия()Полное описание, параметры и ограничения
ОтборСообщенийСистемыВзаимодействия.По умолчанию
ОтборСообщенийСистемыВзаимодействия (CollaborationSystemMessagesFilter)
По умолчанию
Доступен, начиная с версии 8.3.10.
Синтаксис:
Новый ОтборСообщенийСистемыВзаимодействия()
Использование в версии:
Доступен, начиная с версии 8.3.10.
Методическая информация
Практические примеры
Создать свое обсуждение с двумя сообщениями, проверить ответ и обновить собственную карточку
Полный цикл начинается с нового собственного UUID-ключа и реального текущего участника. Создает обсуждение, выключает собственные оповещения, отправляет две учебные карточки, проверяет их IDs/данные/ответ, точную выборку и обновление.
Где и как запускать
Полный серверный общий модуль УчебноеВзаимодействие своей пустой конфигурации УчебноеВзаимодействие85. Реальная работа системы взаимодействия только после вашего ручного запуска в отдельной локальной VM.
Подготовка
Нужны только ваша изолированная VM, новая пустая база8.5.1.1343 и отдельный локальный сервер взаимодействия, не связанный с рабочими абонентами/серверами. Имя конфигурации УчебноеВзаимодействие85, русский язык, совместимость Не использовать, управляемый интерфейс. Пустоту предметных объектов, фоновых заданий, подписок и отсутствие расширений проверяет код. Реальные API здесь не выполнялись.
Разверните собственный учебный сервер взаимодействия в той же VM с локальным адресом http://localhost:9094, без публичной публикации, SMTP, внешних интеграций, совместного использования приложений и чужих учетных записей. Его установку и настройку выполняйте вручную по документации своей серверной поставки. Эта программа не устанавливает сервер и не меняет маршрут localhost. Если фактически зарегистрированный адрес отличается, образец намеренно отказывает; не подставляйте рабочий адрес.
В конфигураторе вручную создайте единственного пользователя с именем Уч85Связь_ и добавленным вашим новым ненулевым UUID в каноническом строковом формате; полное имя Учебный участник. Назначьте только в этом стенде необходимые права Администрирование данных/администрирование пользователей и системы взаимодействия. Войдите под ним. Учетные записи/права этим кодом не создаются и не расширяются.
Вручную зарегистрируйте только эту пустую базу на своем отдельном сервере взаимодействия; наименование приложения задайте УчебноеВзаимодействие85. Синхронизируйте своего внутреннего пользователя базы: имя/полное имя совпадают, учетная запись не внешняя, не заблокирована, без почты/телефона/аутентификационной почты/ключа сопоставления. Для урока профиля псевдоним должен быть пустым. Не используйте персональные сведения, действительные адреса или контакты.
Создайте серверный общий модуль УчебноеВзаимодействие с флагом Сервер, без флагов Клиент и Привилегированный. Вставьте полный код выбранного урока целиком, не одновременно оба варианта модуля. Все вызываемые внутренние функции включены. Нельзя вставлять серверные методы в клиентский модуль формы: thin/web для этих синхронных методов не объявлены в native-справке.
Создайте свою внешнюю обработку с одной управляемой формой, командой Выполнить и строковым реквизитом Подтверждение длиной100. Обработчик команды клиента вызывает ВыполнитьНаСервере(); серверная процедура вызывает УчебноеВзаимодействие.ВыполнитьПример(Подтверждение). Эти две короткие процедуры даны отдельным поддерживающим модулем. Кнопка должна быть нажата сознательно только после чтения предупреждений; автоматического запуска при открытии нет.
В VM оставьте только свой сеанс, не включайте ботов, обработчики сообщений, сторонние клиенты или задания, способные менять свои объекты параллельно. Защитные маркеры/ID уменьшают риск чужого доступа, но не являются криптографическим доказательством собственника сервера и не заменяют вашу проверку выделенного стенда. Профиль и сообщения — настоящие изменения на своем сервере при вашем ручном запуске.
Сначала оставьте подтверждение пустым: программа должна остановиться до изменения профиля/создания обсуждения. Затем введите только фразу выбранного урока. После исключения никакие автоматические повторы/откаты/удаления не выполняются. Сохраните показанный собственный кандидат UUID-ключа/псевдонима и проверяйте возможный частичный результат вручную только в своем сервере. Новые резервные копии не создаются.
Процедура ВыполнитьПример(Подтверждение = "") Экспорт
Пользователь = ПроверитьСвоегоПользователя85();
Если Подтверждение <> "СВОЕ ОБСУЖДЕНИЕ И ДВА СООБЩЕНИЯ" Тогда
ВызватьИсключение "Сначала прочитайте подготовку. Обсуждение не создано";
КонецЕсли;
ИДПользователя = Пользователь.Идентификатор;
Ключ = "Уч85Обсуждение_" + Строка(Новый УникальныйИдентификатор);
Сообщить("Собственный кандидат ключа: " + Ключ);
Если СистемаВзаимодействия.ПолучитьОбсуждение(Ключ) <> Неопределено Тогда
ВызватьИсключение "Коллизия ключа: существующее обсуждение не меняется";
КонецЕсли;
Выбор = Новый КоллекцияИдентификаторовПользователейСистемыВзаимодействия;
Выбор.Добавить(ИДПользователя);
Если Выбор.Количество() <> 1 Или Не Выбор.Содержит(ИДПользователя) Тогда
ВызватьИсключение "Состав своего участника не собран";
КонецЕсли;
Выбор.Удалить(ИДПользователя);
Если Выбор.Количество() <> 0 Или Выбор.Содержит(ИДПользователя) Тогда
ВызватьИсключение "Удаление из локального подбора не подтверждено";
КонецЕсли;
Выбор.Добавить(ИДПользователя);
Выбор.Очистить();
Если Выбор.Количество() <> 0 Тогда
ВызватьИсключение "Локальный подбор не очищен";
КонецЕсли;
Выбор.Добавить(ИДПользователя);
Обсуждение = СистемаВзаимодействия.СоздатьОбсуждение();
Обсуждение.Ключ = Ключ;
Обсуждение.Заголовок = Ключ + " | Проверка карточки книги";
Обсуждение.Групповое = Истина;
Обсуждение.Отображаемое = Истина;
Обсуждение.ТолькоПросмотр = Ложь;
Обсуждение.КонтекстОбсуждения = Неопределено;
Обсуждение.Интеграция = Неопределено;
Обсуждение.ВнешнийИдентификатор = "";
Для Каждого Участник Из Выбор Цикл
Обсуждение.Участники.Добавить(Участник);
КонецЦикла;
Обсуждение.Записать();
ИДОбсуждения = Обсуждение.Идентификатор;
Если ТипЗнч(ИДОбсуждения) <> Тип("ИдентификаторОбсужденияСистемыВзаимодействия") Тогда
ВызватьИсключение "Запись могла произойти, но реальный ID обсуждения не получен";
КонецЕсли;
Сообщить("Свой ID обсуждения: " + Строка(ИДОбсуждения));
Восстановленное = Новый ИдентификаторОбсужденияСистемыВзаимодействия(Строка(ИДОбсуждения));
ПроверитьСвоеОбсуждение85(Восстановленное, Ключ, ИДПользователя);
Отбор = Новый ОтборОбсужденийСистемыВзаимодействия;
Отбор.Ключ = Ключ;
Отбор.Групповое = Истина;
Отбор.Отображаемое = Истина;
Отбор.КонтекстноеОбсуждение = Ложь;
Отбор.КонтекстОбсуждения = Неопределено;
Отбор.ТекущийПользовательЯвляетсяУчастником = Истина;
Отбор.Количество = 2;
Отбор.НаправлениеСортировки = НаправлениеСортировки.Возр;
Отбор.ДатаНачала = Неопределено;
Отбор.ВнешнийИдентификатор = "";
Если Отбор.Интеграция <> Неопределено Тогда
ВызватьИсключение "Новый отбор не должен выбирать внешнюю интеграцию";
КонецЕсли;
Список = СистемаВзаимодействия.ПолучитьОбсуждения(Отбор);
Если Список.Количество() <> 1 Или Список[0].Идентификатор <> ИДОбсуждения Тогда
ВызватьИсключение "Точный отбор собственного обсуждения не совпал";
КонецЕсли;
СистемаВзаимодействия.УстановитьРежимНаблюдения(ИДОбсуждения, Ложь, ИДПользователя);
СистемаВзаимодействия.УстановитьОтображениеОповещенийОбсуждения(ИДОбсуждения,
ОтображениеОповещенийСистемыВзаимодействия.НеБеспокоить, ИДПользователя);
Если СистемаВзаимодействия.ПолучитьРежимНаблюдения(ИДОбсуждения, ИДПользователя)
Или СистемаВзаимодействия.ПолучитьОтображениеОповещенийОбсуждения(ИДОбсуждения, ИДПользователя)
<> ОтображениеОповещенийСистемыВзаимодействия.НеБеспокоить Тогда
ВызватьИсключение "Собственные настройки оповещений не подтверждены";
КонецЕсли;
ПроверитьСвоеОбсуждение85(ИДОбсуждения, Ключ, ИДПользователя);
ОтборДоЗаписи = Новый ОтборСообщенийСистемыВзаимодействия;
ОтборДоЗаписи.Обсуждение = ИДОбсуждения;
ОтборДоЗаписи.Количество = 2;
ОтборДоЗаписи.НаправлениеСортировки = НаправлениеСортировки.Возр;
ОтборДоЗаписи.После = Неопределено;
Если СистемаВзаимодействия.ПолучитьСообщения(ОтборДоЗаписи).Количество() <> 0 Тогда
ВызватьИсключение "Перед первой своей записью обсуждение должно быть пусто";
КонецЕсли;
Исходное = СистемаВзаимодействия.СоздатьСообщение(ИДОбсуждения);
Исходное.Текст = Новый ФорматированнаяСтрока(Ключ + " | Книга: количество 3, цена 250");
Исходное.Данные = Ключ + "|Книга|3|250";
Исходное.ФорматДанныхСтроки = "text/plain";
Исходное.Получатели.Добавить(Новый ИдентификаторПользователяСистемыВзаимодействия);
ПроверитьСвойЧерновик85(Исходное);
Исходное.Записать();
ИДИсходного = Исходное.Идентификатор;
Сообщить("Свой ID первого сообщения: " + Строка(ИДИсходного));
ПервыйФакт = СистемаВзаимодействия.ПолучитьСообщение(
Новый ИдентификаторСообщенияСистемыВзаимодействия(Строка(ИДИсходного)));
ПроверитьСвоеСообщение85(ПервыйФакт, ИДИсходного, ИДОбсуждения, ИДПользователя, Ключ,
Ключ + " | Книга: количество 3, цена 250", Неопределено);
ПроверитьСвоеОбсуждение85(ИДОбсуждения, Ключ, ИДПользователя);
ДоВторойЗаписи = СистемаВзаимодействия.ПолучитьСообщения(ОтборДоЗаписи);
Если ДоВторойЗаписи.Количество() <> 1 Или ДоВторойЗаписи[0].Идентификатор <> ИДИсходного Тогда
ВызватьИсключение "Перед второй своей записью ожидается только подтвержденное первое сообщение";
КонецЕсли;
Второе = СистемаВзаимодействия.СоздатьСообщение(ИДОбсуждения);
Второе.Текст = Новый ФорматированнаяСтрока(Ключ + " | Проверка: сумма 750");
Второе.Данные = Ключ + "|Книга|3|250";
Второе.ФорматДанныхСтроки = "text/plain";
Второе.ИсходноеСообщение = ИДИсходного;
Второе.Получатели.Добавить(Новый ИдентификаторПользователяСистемыВзаимодействия);
ПроверитьСвойЧерновик85(Второе);
Второе.Записать();
ИДВторого = Второе.Идентификатор;
Сообщить("Свой ID второго сообщения: " + Строка(ИДВторого));
ВторойФакт = СистемаВзаимодействия.ПолучитьСообщение(ИДВторого);
ПроверитьСвоеСообщение85(ВторойФакт, ИДВторого, ИДОбсуждения, ИДПользователя, Ключ,
Ключ + " | Проверка: сумма 750", ИДИсходного);
ПроверитьСвойСписок85(ИДОбсуждения, ИДИсходного, ИДВторого);
ПроверитьСвоеОбсуждение85(ИДОбсуждения, Ключ, ИДПользователя);
ВторойФакт = СистемаВзаимодействия.ПолучитьСообщение(ИДВторого);
ПроверитьСвоеСообщение85(ВторойФакт, ИДВторого, ИДОбсуждения, ИДПользователя, Ключ,
Ключ + " | Проверка: сумма 750", ИДИсходного);
ВторойФакт.Текст = Новый ФорматированнаяСтрока(Ключ + " | Проверка подтверждена: 750");
ВторойФакт.Записать();
ПроверитьСвоеСообщение85(СистемаВзаимодействия.ПолучитьСообщение(ИДВторого),
ИДВторого, ИДОбсуждения, ИДПользователя, Ключ,
Ключ + " | Проверка подтверждена: 750", ИДИсходного);
Сообщить("Два своих сообщения сохранены, отобраны и одно обновлено. Удаление не выполняется автоматически");
КонецПроцедуры
Процедура ПроверитьСвойЧерновик85(Сообщение)
Если Сообщение.Вложения.Количество() <> 0 Или Сообщение.Действия.Количество() <> 0
Или Сообщение.ПанельКнопок.РядыКнопок.Количество() <> 0
Или Сообщение.ЗначенияПодстановокШаблонаСообщения.Количество() <> 0
Или Сообщение.ШаблонСообщения <> Неопределено Тогда
ВызватьИсключение "Новый собственный черновик содержит неподготовленные вложения или шаблон";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоеОбсуждение85(Идентификатор, Ключ, Участник)
Факт = СистемаВзаимодействия.ПолучитьОбсуждение(Идентификатор);
Если Факт.Идентификатор <> Идентификатор Или Факт.Ключ <> Ключ
Или Факт.Заголовок <> Ключ + " | Проверка карточки книги"
Или Не Факт.Групповое Или Не Факт.Отображаемое Или Факт.ТолькоПросмотр
Или Факт.КонтекстОбсуждения <> Неопределено Или Факт.Интеграция <> Неопределено
Или Факт.ВнешнийИдентификатор <> ""
Или Факт.Участники.Количество() <> 1 Или Не Факт.Участники.Содержит(Участник) Тогда
ВызватьИсключение "Полный собственный паспорт обсуждения изменен или не совпал";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоеСообщение85(Факт, Идентификатор, Обсуждение, Автор, Ключ, Текст, Исходное)
Если Факт.Идентификатор <> Идентификатор Или Факт.Обсуждение <> Обсуждение
Или Факт.Автор <> Автор Или Строка(Факт.Текст) <> Текст
Или Факт.Данные <> Ключ + "|Книга|3|250" Или Факт.ФорматДанныхСтроки <> "text/plain"
Или Факт.ИсходноеСообщение <> Исходное Или ТипЗнч(Факт.Дата) <> Тип("Дата")
Или Факт.Дата = Дата(1, 1, 1) Тогда
ВызватьИсключение "Полное собственное сообщение не подтверждено. Чужое содержимое не выводится";
КонецЕсли;
ПроверитьСвойЧерновик85(Факт);
КонецПроцедуры
Процедура ПроверитьСвойСписок85(Обсуждение, Первый, Второй)
Отбор = Новый ОтборСообщенийСистемыВзаимодействия;
Отбор.Обсуждение = Обсуждение;
Отбор.Количество = 3;
Отбор.НаправлениеСортировки = НаправлениеСортировки.Возр;
Отбор.После = Неопределено;
Список = СистемаВзаимодействия.ПолучитьСообщения(Отбор);
Если Список.Количество() <> 2 Тогда
ВызватьИсключение "В собственном обсуждении должно быть ровно два собственных сообщения";
КонецЕсли;
Для Каждого СтрокаСообщения Из Список Цикл
Если СтрокаСообщения.Обсуждение <> Обсуждение
Или СтрокаСообщения.Идентификатор <> Первый И СтрокаСообщения.Идентификатор <> Второй Тогда
ВызватьИсключение "В список попало неподтвержденное сообщение";
КонецЕсли;
КонецЦикла;
Отбор.После = Второй;
Если СистемаВзаимодействия.ПолучитьСообщения(Отбор).Количество() <> 0 Тогда
ВызватьИсключение "После второго собственного сообщения не ожидаются записи";
КонецЕсли;
КонецПроцедуры
Функция ПроверитьСвоегоПользователя85()
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Входной привилегированный режим не допускается";
КонецЕсли;
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователи.Количество() <> 1 Или Текущий = Неопределено Тогда
ВызватьИсключение "Нужен единственный собственный учебный пользователь";
КонецЕсли;
Если Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор
Или Лев(Текущий.Имя, СтрДлина("Уч85Связь_")) <> "Уч85Связь_" Тогда
ВызватьИсключение "Учебный пользователь не подтвержден";
КонецЕсли;
UUIDМетки = Новый УникальныйИдентификатор(Сред(Текущий.Имя, СтрДлина("Уч85Связь_") + 1));
Если Текущий.Имя <> "Уч85Связь_" + Строка(UUIDМетки)
Или UUIDМетки = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000") Тогда
ВызватьИсключение "Имя должно содержать собственный канонический ненулевой UUID";
КонецЕсли;
Если Не СистемаВзаимодействия.ИнформационнаяБазаЗарегистрирована()
Или Не СистемаВзаимодействия.ИспользованиеДоступно() Тогда
ВызватьИсключение "Вручную подготовьте регистрацию собственной учебной базы";
КонецЕсли;
Если СистемаВзаимодействия.АдресСервера() <> "http://localhost:9094" Тогда
ВызватьИсключение "Разрешен только отдельно подготовленный сервер localhost:9094 в своей VM";
КонецЕсли;
Версия = СистемаВзаимодействия.ВерсияСервера();
Если ТипЗнч(Версия) <> Тип("Строка") Или Не ЗначениеЗаполнено(Версия) Тогда
ВызватьИсключение "Версия своего сервера не получена";
КонецЕсли;
ИД = СистемаВзаимодействия.ИдентификаторТекущегоПользователя();
Если ТипЗнч(ИД) <> Тип("ИдентификаторПользователяСистемыВзаимодействия") Тогда
ВызватьИсключение "Не получен реальный идентификатор собственного участника";
КонецЕсли;
Если СистемаВзаимодействия.ПолучитьИдентификаторПользователя(Текущий.УникальныйИдентификатор) <> ИД
Или СистемаВзаимодействия.ПолучитьИдентификаторПользователяИнформационнойБазы(ИД) <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Двустороннее соответствие своей учетной записи неверно";
КонецЕсли;
Пользователь = СистемаВзаимодействия.ПолучитьПользователя(ИД);
Если Пользователь.Идентификатор <> ИД Или Пользователь.Имя <> Текущий.Имя
Или Пользователь.ПолноеИмя <> Текущий.ПолноеИмя
Или Пользователь.ИдентификаторПользователяИнформационнойБазы <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Паспорт своего пользователя не совпал с информационной базой";
КонецЕсли;
Если Пользователь.Внешний Или Пользователь.Заблокирован
Или Пользователь.ТипВнешнейСистемы <> ""
Или Пользователь.ИдентификаторПользователяВнешнейСистемы <> Неопределено
Или Пользователь.АдресЭлектроннойПочты <> ""
Или Пользователь.АдресЭлектроннойПочтыДляАутентификации <> ""
Или Пользователь.НомерТелефона <> ""
Или Пользователь.КлючСопоставления <> "" Тогда
ВызватьИсключение "Нужен чистый внутренний пользователь без персональных контактов и объединений";
КонецЕсли;
Если Пользователь.АдминистраторАбонента <> СистемаВзаимодействия.ТекущийПользовательЯвляетсяАдминистраторомАбонента() Тогда
ВызватьИсключение "Признак администратора абонента не согласован";
КонецЕсли;
ВсеПользователи = СистемаВзаимодействия.СтандартныеПользователи.ВсеПользователиПриложения;
Если ИД = ВсеПользователи Или ИД = Новый ИдентификаторПользователяСистемыВзаимодействия Тогда
ВызватьИсключение "Стандартный адресат и Никого не оповещать не являются своей учетной записью";
КонецЕсли;
ВосстановленныйИД = Новый ИдентификаторПользователяСистемыВзаимодействия(Строка(ИД));
Если СистемаВзаимодействия.ПолучитьПользователя(ВосстановленныйИД).Идентификатор <> ИД Тогда
ВызватьИсключение "Восстановленный из строки реальный ID не подтвержден сервером";
КонецЕсли;
Приложение = СистемаВзаимодействия.ПолучитьПриложение(СистемаВзаимодействия.ИдентификаторТекущегоПриложения());
Если Приложение.Идентификатор <> СистемаВзаимодействия.ИдентификаторТекущегоПриложения()
Или Приложение.Наименование <> "УчебноеВзаимодействие85" Тогда
ВызватьИсключение "Нужно свое приложение с точным учебным наименованием";
КонецЕсли;
Возврат Пользователь;
КонецФункции
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедурыМодуль своей управляемой формы: команда и серверный вызов
Своя внешняя обработка → основная управляемая форма → модуль формы
Полный клиентский обработчик команды и серверная процедура этой формы; общий модуль отдельно. Не вставляйте общий модуль внутрь обработчика.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
КонецПроцедуры
&НаСервере
Процедура ВыполнитьНаСервере()
УчебноеВзаимодействие.ВыполнитьПример(Подтверждение);
КонецПроцедурыРазбор по шагам
Сначала повторяется полный паспорт своего стенда/участника/приложения. Подтверждение СВОЕ ОБСУЖДЕНИЕ И ДВА СООБЩЕНИЯ обязательно. Новый Ключ из UUID выводится до первой серверной записи; ПолучитьОбсуждение(Ключ) должен вернуть Неопределено, существующий чат не переиспользуется.
Отдельная локальная КоллекцияИдентификаторовПользователей демонстрирует Добавить/Содержит/Количество/Удалить/Очистить с настоящим своим участником. Это подбор в памяти, не удаление серверной учетной записи. В окончательном составе снова ровно один свой ID.
СоздатьОбсуждение возвращает объект еще до серверного создания. Только новому объекту задаются Ключ, Групповое, ТолькоПросмотр, КонтекстОбсуждения, Интеграция и ВнешнийИдентификатор. Никакой внешней интеграции нет, контекст пуст, заголовок содержит свою метку; readonly Участники не заменяются массивом, а наполняются Добавить.
После Записать получен реальный readonly ID, выводится только он. Конструктор ID обсуждения принимает Строка этого фактического ID. Новый ПолучитьОбсуждение проверяет весь паспорт: ключ/заголовок/флаги/пустые внешние значения/ровно свой участник.
ОтборОбсуждений ограничивается своим точным Ключом, групповым видимым неконтекстным режимом и текущим участником; Количество=2 обнаруживает неожиданные записи. ДатаНачала=Неопределено не гадает часовой пояс/время первого сообщения. Readonly Интеграция только проверяется на отсутствие, не назначается.
УстановитьРежимНаблюдения(false) и УстановитьОтображениеОповещенийОбсуждения(НеБеспокоить) применяются только к новому своему обсуждению/текущему участнику. Оба значения читаются заново. Это два разных состояния, не блокировка доставки сообщений или серверной записи.
СоздатьСообщение требует реальный ИдентификаторОбсуждения, не строковый UUID и не объект обсуждения. Текст — настоящий Новый ФорматированнаяСтрока, Данные — небольшая собственная строка, MIME text/plain. В Получатели добавлен пустой ID со специальной семантикой Никого не оповещать, не все пользователи приложения.
Черновик должен не иметь непредусмотренных вложений/действий/кнопок/шаблона/подстановок. После Записать первый реальный ID сохраняется и читается через собственный строковый roundtrip. Паспорт включает обсуждение, автора, точный текст, небольшие данные, MIME, отсутствие исходного ответа и ненулевую серверную дату; чужое содержимое не выводится.
Вторая карточка с суммой750 создается в том же собственном обсуждении, а ИсходноеСообщение получает реальный ID первой. Fresh read подтверждает именно эту связь. ШаблонСообщения не устанавливается: шаблонный режим иначе игнорировал бы обычные Текст/Данные/Действия.
ОтборСообщений ограничен собственным обсуждением, Количество=3 позволяет обнаружить лишнюю третью запись. Получено ровно два допустимых собственных ID; никаких чужих ID/текстов не печатается. После второго ID в Возр ожидается пустая страница.
Перед обновлением заново проверяются обсуждение и свежая вторая карточка с исходным текстом/данными/автором. Только её Текст меняется на Проверка подтверждена:750 и Записать. Повторное ПолучитьСообщение подтверждает измененный текст при том же реальном ID/данных/ответе.
Удаления и отката нет. Новый чат, два сообщения и настройки остаются учебными артефактами для вашей ручной проверки. При исключении программа не посылает карточки заново и не удаляет что-либо в catch; показанный ключ и полученные IDs служат только собственной ручной сверке частичного состояния.
Как проверить результат
Без правильной фразы, при втором пользователе, внешних данных, неверном приложении/адресе, коллизии или неподготовленных правах Записать не должен выполняться до соответствующего guard.
В собственном интерфейсе после положительного ручного опыта новый UUID-чат содержит карточку Книги и ответ с подтвержденной суммой750. Список участников — только ваш пользователь, подключенных внешних интеграций/контекстного объекта нет.
Fresh read первого/второго IDs проверяет точные Текст, Данные, text/plain, автора и связь ответа. Строковое восстановление идентификаторов не является доказательством существования до этих real reads.
Первый отбор обсуждений возвращает ровно один свой чат, отбор сообщений — ровно два своих ID, следующая страница после второго пуста. Лишняя третья карточка или посторонний ID должны остановить урок до изменения второй.
У своего обсуждения РежимНаблюдения=false и ОтображениеОповещений=НеБеспокоить. Отсутствие визуального оповещения не используется как доказательство, что сообщения не записаны или не доставлены.
Второй ID после изменения тот же, ИсходноеСообщение равно первому ID, Текст изменен и отдельно прочитан. После ошибки/потери ответа проверьте частичный результат вручную по своему ключу; автоматического повтора/удаления нет.
Ожидаемый результат
На отдельном своем сервере создан собственный UUID-чат, две реальные карточки с проверенной связью ответа и одна подтвержденная правка; отборы и собственные настройки оповещений проверены либо зафиксирован конкретный отказ. Никакой сетевой опыт здесь не выполнялся.
На что обратить внимание
Синхронные СоздатьОбсуждение/СоздатьСообщение/ПолучитьСообщения/Записать доступны на сервере, не в тонком клиентском обработчике. Асинхронные методы не имитируются синхронными; неоднозначная native-страница ПолучитьОбсуждениеАсинх здесь не используется.
Идентификаторы обсуждения/сообщения конструктором по строке не валидируются. Ввод пользовательского произвольного ID не разрешен: только ID объектов, созданных этим опытом, и свежее подтверждение их паспорта.
Ключ уникален в пределах базы с учетом независимых разделителей, а не глобально по всем серверам. UUID не гарантирует владение чужим сервером; требуется отдельная VM и вручную проверенная регистрация своего приложения.
Групповое, ТолькоПросмотр, Ключ, КонтекстОбсуждения, Интеграция и ВнешнийИдентификатор могут назначаться только новому обсуждению. Заголовок на клиенте readonly. Участники/Получатели readonly как свойства, но методы их коллекций изменяют состав.
Данные сериализуются сервером в JSON с ограничением100Кб и требованиями XDTO. Урок посылает маленькую строку со своей меткой; он не демонстрирует передачу ссылок базы/секретов/объектов с неподдерживаемой сериализацией. Серверную Дата и Автор код только читает, не подменяет.
Пустой ID адресата означает Никого не оповещать; это не конкретный пользователь и не запрет серверной записи/чтения. РежимНеБеспокоить и РежимНаблюдения тоже не являются настройками безопасности или запретом доставки.
Пагинация После задает относительное положение по серверной сортировке. Два сообщения иногда имеют одинаковую дату, поэтому урок не требует различия секунд или самодельной сортировки ID. Отказ пустой следующей страницы требует ручной сверки, не догадки об успехе.
Проверка/обновление не атомарны, нет транзакционного отката внешнего сервера и автоматического удаления созданного чата. Не запускайте параллельных клиентов/ботов. При потере ответа запись могла выполниться; список/ключ/ID сверяйте вручную только на своем сервере.
Права Администрирование данных на новом стенде заранее нужны для ТолькоПросмотр и получения списка пользователей; privilege не включается программой. Сервер/аккаунты/права/сообщения реально не создавались и сеть не вызывалась. RuntimeVerifiedScenarios=0.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.
Создать свою выгрузку взаимодействия, проверить готовность, восстановить две карточки и удалить только свой файл
Полный пульт отличает начало выгрузки/восстановления от окончания. Источник — ровно две собственные карточки полного подготовительного модуля, файлы/ID создаются самим пультом, mutation/delete допускаются только после свежего паспорта и точного собственного подтверждения.
Где и как запускать
Полный модуль управляемой формы УчебнаяВыгрузка85 собственного пустого УчебноеВзаимодействие85. Синхронные RPC и клиентское Ждать, все собственные проверки включены; серверный подготовительный модуль ниже создает конкретный источник.
Подготовка
Только отдельная собственная VM, пустая учебная конфигурация УчебноеВзаимодействие858.5.1.1343, один UUID-пользователь Уч85Связь_, приложение УчебноеВзаимодействие85 и собственный сервер взаимодействия http://localhost:9094. Подготовьте их как в учебном модуле двух карточек, включенном ниже. Никакого рабочего абонента/совместного использования/интеграций/фона/персональных данных. Код не выполнялся и не создал резервных копий.
В своем сервере вручную включите штатное локальное хранение выгрузок, разрешенное вашей серверной поставкой. Для файлового режима адрес будет путем на СЕРВЕРЕ ВЗАИМОДЕЙСТВИЯ, не сервере1С/клиенте. Для S3-ветви допустимо только отдельное локальное S3-совместимое хранилище http://localhost:9000/, без AWS/публичных бакетов. Это настройка вручную по документации вашего сервера; код не устанавливает хранилище и не подменяет его совместимость.
Выдайте в этом новом стенде необходимые права администрирования данных/системы взаимодействия, настройки своего сервера/выгрузок. Никакое право не повышается кодом. Для положительного пути этой учебной партии выберите thin/thick управляемый клиент VM; наличие веб/mobile API не является проверкой этих клиентов.
Создайте серверный общий модуль УчебноеВзаимодействие без Привилегированный, вставьте полный подготовительный модуль ниже. Вызовите его своей отдельной ручной командой с фразой СВОЕ ОБСУЖДЕНИЕ И ДВА СООБЩЕНИЯ. Он создаст собственный UUID-чат/две карточки и обновит второй текст до Проверка подтверждена:750. Сохраните показанный ключ только этого опыта; не подбирайте чужие чаты.
Создайте другую внешнюю обработку УчебнаяВыгрузка85 с одной управляемой формой. Строки: Метка85 и Описание85 длиной200, IDВыгрузки85 и ПодтверждениеУдаления85 длиной100, ИсходныйКлюч85 длиной100, Режим85 длиной20, Фаза85 длиной30, Подтверждение85 длиной100, Статус85 длиной0. Булево НеизвестныйИсход85 и НачатоВосстановление85. Метка, описание, ID, фаза, флаги и статус только для просмотра/скрыты, не пользовательский выбор ID.
Пять команд Создать85, Проверить85, Описание85, Восстановить85, Удалить85: общее действие ВыполнитьОперацию85. Назначьте ПриСозданииНаСервере/ПриОткрытии, вставьте весь основной модуль этой формы. Начальный список выгрузок своего приложения должен быть пуст — существующие выгрузки не переиспользуются и не удаляются.
Введите только собственный ИсходныйКлюч85 из подготовительного опыта, выберите один режим Сервер или Ждать и фразу ТОЛЬКО СВОИ ДВЕ КАРТОЧКИ И ВЫГРУЗКА. Каждый режим изучайте на отдельном собственном свежем сервере/приложении. Сначала проверьте пустую фразу: никаких изменений. Создать85 начинает настоящую выгрузку только при вашем сознательном ручном запуске; файлы действительно появятся на вашем сервере, не здесь.
После Создать85 нажимайте Проверить85 вручную с разумной паузой. Автотаймера/плотного цикла нет. Только статус Готово позволяет Описание85/Восстановить85/Удалить85. Восстановить85 сначала меняет собственный ответ750 на999, затем начинает восстановление именно своего снимка. Оно может перезаписать данные всего своего приложения, поэтому абсолютно все приложение и сервер должны быть только вашим учебным стендом.
Если проверка восстановленного снимка нужна, дождитесь СтатусВосстановления=Успешно и свежего чтения исходных обеих карточек. Затем для необратимого удаления единственного собственного файла введите точный показанный IDВыгрузки85 в ПодтверждениеУдаления85. Возврата удаленного файла код не предлагает; сообщения/приложение этим методом не удаляются.
При неизвестном результате пульт разрешает только чтение и не сбрасывает защитный флаг. Не повторяйте создание/правку/восстановление/удаление автоматически. При аварийном закрытии собственные метка/ID могут потеряться: это не повод подбирать старый файл. Автор не выполнял сеть/выгрузку/восстановление/удаление и не создавал архивов/резервных копий.
&НаКлиенте
Перем Выполняется85;
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ПроверитьСвоегоПользователя85();
Если СистемаВзаимодействия.ПолучитьВыгрузкуДанных().Количество() <> 0 Тогда
ВызватьИсключение "В выделенном своем приложении не должно быть прежних выгрузок";
КонецЕсли;
Метка85 = "Уч85Выгрузка_" + Строка(Новый УникальныйИдентификатор);
Описание85 = Метка85 + " | Две собственные учебные карточки";
IDВыгрузки85 = "";
ИсходныйКлюч85 = "";
Режим85 = "Сервер";
Фаза85 = "Новая";
Подтверждение85 = "";
ПодтверждениеУдаления85 = "";
НеизвестныйИсход85 = Ложь;
НачатоВосстановление85 = Ложь;
Статус85 = "Укажите точный свой UUID-ключ двух карточек, созданных этим учебным стендом";
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Выполняется85 = Ложь;
КонецПроцедуры
&НаКлиенте
Асинх Процедура ВыполнитьОперацию85(Команда)
Если Выполняется85 Тогда
ВызватьИсключение "Предыдущая операция пульта еще выполняется";
КонецЕсли;
Если Фаза85 = "Удалено" Тогда
ВызватьИсключение "Опыт завершен. Новый пульт не подбирает прежние ID";
КонецЕсли;
Операция = Команда.Имя;
Если Операция <> "Создать85" И Операция <> "Проверить85" И Операция <> "Описание85"
И Операция <> "Восстановить85" И Операция <> "Удалить85" Тогда
ВызватьИсключение "Неизвестная учебная операция выгрузки";
КонецЕсли;
Если НеизвестныйИсход85 И Операция <> "Проверить85" Тогда
ВызватьИсключение "Исход записи неизвестен. Только чтение; повтор и удаление запрещены";
КонецЕсли;
Если Режим85 <> "Сервер" И Режим85 <> "Ждать" Тогда
ВызватьИсключение "Нужен режим Сервер или Ждать";
КонецЕсли;
Если Подтверждение85 <> "ТОЛЬКО СВОИ ДВЕ КАРТОЧКИ И ВЫГРУЗКА" Тогда
ВызватьИсключение "Подтвердите собственный выделенный сервер и данные";
КонецЕсли;
Выполняется85 = Истина;
Попытка
ПроверитьСвоиДанныеНаСервере85(Ложь);
Если Операция = "Создать85" Тогда
Если Фаза85 <> "Новая" Или IDВыгрузки85 <> "" Тогда
ВызватьИсключение "Новая выгрузка уже могла быть создана";
КонецЕсли;
ПроверитьСвоиДанныеНаСервере85(Истина);
Если Режим85 = "Ждать" Тогда
Список = Ждать СистемаВзаимодействия.ПолучитьВыгрузкиДанныхАсинх();
Если ТипЗнч(Список) <> Тип("Массив") Или Список.Количество() <> 0 Тогда
ВызватьИсключение "Перед созданием список выгрузок своего приложения должен быть пуст";
КонецЕсли;
НеизвестныйИсход85 = Истина;
ИД = Ждать СистемаВзаимодействия.НачатьСозданиеВыгрузкиДанныхАсинх(Описание85);
Иначе
НеизвестныйИсход85 = Истина;
ИД = СоздатьСвоюВыгрузкуНаСервере85();
КонецЕсли;
Если ТипЗнч(ИД) <> Тип("ИдентификаторВыгрузкиДанныхСистемыВзаимодействия") Тогда
ВызватьИсключение "Создание могло начаться, но реальный ID не подтвержден";
КонецЕсли;
IDВыгрузки85 = Строка(ИД);
Фаза85 = "Создание";
НеизвестныйИсход85 = Ложь;
Статус85 = "Получен только ID начатой своей выгрузки. Файл еще не объявляется готовым";
Иначе
Если IDВыгрузки85 = "" Тогда
ВызватьИсключение "Нет полученного этим пультом собственного ID";
КонецЕсли;
ИД = Новый ИдентификаторВыгрузкиДанныхСистемыВзаимодействия(IDВыгрузки85);
Если Режим85 = "Ждать" Тогда
Факт = Ждать СистемаВзаимодействия.ПолучитьВыгрузкуДанныхАсинх(ИД);
Иначе
Факт = ПолучитьСвоюВыгрузкуНаСервере85(ИД);
КонецЕсли;
ПроверитьСвойПаспортВыгрузки85(Факт, ИД);
Если Операция = "Проверить85" Тогда
ПоказатьСвойСтатус85(Факт);
Если Факт.Статус = СтатусВыгрузкиДанныхСистемыВзаимодействия.Готово Тогда
Если Режим85 = "Ждать" Тогда
Адрес = Ждать СистемаВзаимодействия.ПолучитьАдресВыгрузкиДанныхАсинх(ИД);
Иначе
Адрес = ПолучитьСвойАдресНаСервере85(ИД);
КонецЕсли;
ПроверитьСвойАдрес85(Адрес, Факт.ДоступнаВыгрузка);
Если НачатоВосстановление85 И Факт.СтатусВосстановления = СтатусВосстановленияИзВыгрузкиДанныхСистемыВзаимодействия.Успешно Тогда
ПроверитьСвоиДанныеНаСервере85(Истина);
Фаза85 = "Восстановлено";
Статус85 = "Своя выгрузка сообщает Успешно и исходные две карточки прочитаны заново";
ИначеЕсли Не НачатоВосстановление85 Тогда
Фаза85 = "Готово";
КонецЕсли;
КонецЕсли;
Иначе
Если Факт.Статус <> СтатусВыгрузкиДанныхСистемыВзаимодействия.Готово
Или Фаза85 <> "Готово" И Фаза85 <> "Восстановлено" Тогда
ВызватьИсключение "Мутация допускается только после ручной проверки готовности своего файла";
КонецЕсли;
Если Операция = "Описание85" Тогда
Если СтрНайти(Описание85, " | Описание подтверждено") <> 0 Тогда
ВызватьИсключение "Описание уже изменено этим опытом";
КонецЕсли;
НовоеОписание = Описание85 + " | Описание подтверждено";
НеизвестныйИсход85 = Истина;
Если Режим85 = "Ждать" Тогда
Результат = Ждать СистемаВзаимодействия.УстановитьОписаниеВыгрузкиДанныхАсинх(ИД, НовоеОписание);
Если Результат <> Неопределено Тогда
ВызватьИсключение "Native-результат изменения описания должен быть Неопределено";
КонецЕсли;
После = Ждать СистемаВзаимодействия.ПолучитьВыгрузкуДанныхАсинх(ИД);
Иначе
После = ИзменитьСвоеОписаниеНаСервере85(ИД, НовоеОписание);
КонецЕсли;
Если После.Идентификатор <> ИД Или После.Описание <> НовоеОписание Тогда
ВызватьИсключение "Новое описание собственной выгрузки не подтверждено";
КонецЕсли;
Описание85 = НовоеОписание;
НеизвестныйИсход85 = Ложь;
Статус85 = "Своё описание изменено API и отдельно прочитано, readonly свойство не назначалось";
ИначеЕсли Операция = "Восстановить85" Тогда
Если НачатоВосстановление85 Тогда
ВызватьИсключение "Восстановление уже могло начаться. Повтор запрещен";
КонецЕсли;
НеизвестныйИсход85 = Истина;
НачатоВосстановление85 = Истина;
ИзменитьТолькоСвоюКарточкуПередВосстановлением85();
Если Режим85 = "Ждать" Тогда
Результат = Ждать СистемаВзаимодействия.НачатьВосстановлениеИзВыгрузкиДанныхАсинх(ИД);
Если Результат <> Неопределено Тогда
ВызватьИсключение "Начало восстановления обещанием должно дать Неопределено";
КонецЕсли;
Иначе
НачатьСвоеВосстановлениеНаСервере85(ИД);
КонецЕсли;
Фаза85 = "Восстановление";
НеизвестныйИсход85 = Ложь;
Статус85 = "Восстановление только начато. Нажимайте Проверить85 вручную до подтвержденного статуса и двух исходных карточек";
Иначе
Если ПодтверждениеУдаления85 <> IDВыгрузки85 Тогда
ВызватьИсключение "Для необратимого удаления введите только точный свой ID выгрузки";
КонецЕсли;
Если НачатоВосстановление85 И Фаза85 <> "Восстановлено" Тогда
ВызватьИсключение "Нельзя удалять файл, пока свой опыт восстановления не подтвержден";
КонецЕсли;
НеизвестныйИсход85 = Истина;
Если Режим85 = "Ждать" Тогда
Результат = Ждать СистемаВзаимодействия.УдалитьВыгрузкуДанныхАсинх(ИД);
Если Результат <> Неопределено Тогда
ВызватьИсключение "Native-результат удаления должен быть Неопределено";
КонецЕсли;
Остаток = Ждать СистемаВзаимодействия.ПолучитьВыгрузкиДанныхАсинх();
Иначе
Остаток = УдалитьТолькоСвоюВыгрузкуНаСервере85(ИД);
КонецЕсли;
Если ТипЗнч(Остаток) <> Тип("Массив") Или Остаток.Количество() <> 0 Тогда
ВызватьИсключение "Отсутствие своего файла в изначально пустом списке не подтверждено";
КонецЕсли;
Фаза85 = "Удалено";
НеизвестныйИсход85 = Ложь;
Статус85 = "Свой единственный файл выгрузки удален. Сообщения и приложение не удалялись";
КонецЕсли;
КонецЕсли;
КонецЕсли;
Исключение
Выполняется85 = Ложь;
Статус85 = "Операция не подтверждена. Сохраните только свою метку/ID и проверьте свой сервер вручную; повторных записей нет";
ВызватьИсключение "Учебная операция прервана без вывода адреса файла, ключей и чужих текстов";
КонецПопытки;
Выполняется85 = Ложь;
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьСвойПаспортВыгрузки85(Факт, ИД)
Если ТипЗнч(Факт) <> Тип("ВыгрузкаДанныхСистемыВзаимодействия")
Или Факт.Идентификатор <> ИД Или Факт.Описание <> Описание85
Или ТипЗнч(Факт.ДатаСоздания) <> Тип("Дата") Или Факт.ДатаСоздания = Дата(1, 1, 1)
Или ТипЗнч(Факт.ДоступнаВыгрузка) <> Тип("Булево") Тогда
ВызватьИсключение "Полный паспорт своей выгрузки не совпал";
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПоказатьСвойСтатус85(Факт)
Если Факт.Статус = СтатусВыгрузкиДанныхСистемыВзаимодействия.Ошибка
Или Факт.СтатусВосстановления = СтатусВосстановленияИзВыгрузкиДанныхСистемыВзаимодействия.Ошибка Тогда
ВызватьИсключение "Сервер сообщил ошибку своего файла или восстановления";
КонецЕсли;
Если Факт.Статус = СтатусВыгрузкиДанныхСистемыВзаимодействия.Создание Тогда
Статус85 = "Создание еще выполняется. Готовности нет";
ИначеЕсли Факт.Статус = СтатусВыгрузкиДанныхСистемыВзаимодействия.Загрузка Тогда
ВызватьИсключение "В этом опыте загрузка чужого файла не начиналась";
ИначеЕсли Факт.Статус = СтатусВыгрузкиДанныхСистемыВзаимодействия.Восстановление Тогда
Если Не НачатоВосстановление85 Тогда
ВызватьИсключение "Неожиданное восстановление вне своего опыта";
КонецЕсли;
Статус85 = "Свое восстановление еще выполняется. Неопределено не означает, что оно никогда не начиналось";
ИначеЕсли Факт.Статус = СтатусВыгрузкиДанныхСистемыВзаимодействия.Готово Тогда
Статус85 = "Свой файл готов по статусу. Готовность не заменяет проверку результата восстановления";
Иначе
ВызватьИсключение "Неизвестный статус не выдается за готовность";
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьСвойАдрес85(Адрес, ДоступноСкачивание)
Если ТипЗнч(Адрес) <> Тип("Строка") Или Не ЗначениеЗаполнено(Адрес) Тогда
ВызватьИсключение "Адрес своего готового файла не получен";
КонецЕсли;
Если ДоступноСкачивание Тогда
Если Лев(Адрес, СтрДлина("http://localhost:9000/")) <> "http://localhost:9000/" Тогда
ВызватьИсключение "S3-ссылка должна вести только в собственное локальное хранилище";
КонецЕсли;
Статус85 = Статус85 + " | Получена ограниченная по времени ссылка только на свой localhost S3; скачивание не выполнено";
Иначе
Если Лев(Адрес, 7) = "http://" Или Лев(Адрес, 8) = "https://" Тогда
ВызватьИсключение "При файловом хранении ожидается путь на сервере взаимодействия, не публичный URL";
КонецЕсли;
Статус85 = Статус85 + " | Получен путь на сервере взаимодействия, не путь клиента/сервера1С; файл не открывался";
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция СоздатьСвоюВыгрузкуНаСервере85()
ПроверитьСвоиДанныеНаСервере85(Истина);
Если СистемаВзаимодействия.ПолучитьВыгрузкуДанных().Количество() <> 0 Тогда
ВызватьИсключение "Начальный список должен быть пустым";
КонецЕсли;
Возврат СистемаВзаимодействия.НачатьСозданиеВыгрузкиДанных(Описание85);
КонецФункции
&НаСервере
Функция ПолучитьСвоюВыгрузкуНаСервере85(ИД)
ПроверитьСвоиДанныеНаСервере85(Ложь);
Возврат СистемаВзаимодействия.ПолучитьВыгрузкуДанных(ИД);
КонецФункции
&НаСервере
Функция ПолучитьСвойАдресНаСервере85(ИД)
ПроверитьСвоюГотовуюВыгрузкуНаСервере85(ИД);
Возврат СистемаВзаимодействия.ПолучитьАдресВыгрузкиДанных(ИД);
КонецФункции
&НаСервере
Функция ИзменитьСвоеОписаниеНаСервере85(ИД, НовоеОписание)
ПроверитьСвоюГотовуюВыгрузкуНаСервере85(ИД);
Если НовоеОписание <> Описание85 + " | Описание подтверждено" Тогда
ВызватьИсключение "Нет собственного ожидаемого описания";
КонецЕсли;
СистемаВзаимодействия.УстановитьОписаниеВыгрузкиДанных(ИД, НовоеОписание);
Возврат СистемаВзаимодействия.ПолучитьВыгрузкуДанных(ИД);
КонецФункции
&НаСервере
Процедура НачатьСвоеВосстановлениеНаСервере85(ИД)
ПроверитьСвоюГотовуюВыгрузкуНаСервере85(ИД);
СистемаВзаимодействия.НачатьВосстановлениеИзВыгрузкиДанных(ИД);
КонецПроцедуры
&НаСервере
Функция УдалитьТолькоСвоюВыгрузкуНаСервере85(ИД)
ПроверитьСвоюГотовуюВыгрузкуНаСервере85(ИД);
Если ПодтверждениеУдаления85 <> IDВыгрузки85 Или Строка(ИД) <> IDВыгрузки85 Тогда
ВызватьИсключение "Точный свой ID удаления не подтвержден";
КонецЕсли;
СистемаВзаимодействия.УдалитьВыгрузкуДанных(ИД);
Возврат СистемаВзаимодействия.ПолучитьВыгрузкуДанных();
КонецФункции
&НаСервере
Процедура ПроверитьСвоюГотовуюВыгрузкуНаСервере85(ИД)
ПроверитьСвоиДанныеНаСервере85(Ложь);
Если Строка(ИД) <> IDВыгрузки85 Или IDВыгрузки85 = "" Тогда
ВызватьИсключение "Не тот реальный ID, который создал собственный пульт";
КонецЕсли;
Факт = СистемаВзаимодействия.ПолучитьВыгрузкуДанных(ИД);
Если Факт.Идентификатор <> ИД Или Факт.Описание <> Описание85
Или Факт.Статус <> СтатусВыгрузкиДанныхСистемыВзаимодействия.Готово Тогда
ВызватьИсключение "Свой готовый файл не подтвержден свежим чтением";
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПроверитьСвоиДанныеНаСервере85(ИсходныйТекст)
Пользователь = ПроверитьСвоегоПользователя85();
Если Лев(ИсходныйКлюч85, СтрДлина("Уч85Обсуждение_")) <> "Уч85Обсуждение_" Тогда
ВызватьИсключение "Укажите свой ключ, созданный полным учебным модулем двух карточек";
КонецЕсли;
UUIDКлюча = Новый УникальныйИдентификатор(Сред(ИсходныйКлюч85, СтрДлина("Уч85Обсуждение_") + 1));
Если ИсходныйКлюч85 <> "Уч85Обсуждение_" + Строка(UUIDКлюча) Тогда
ВызватьИсключение "Нужен канонический собственный UUID-ключ";
КонецЕсли;
Обсуждение = СистемаВзаимодействия.ПолучитьОбсуждение(ИсходныйКлюч85);
Если Обсуждение = Неопределено Или Обсуждение.Ключ <> ИсходныйКлюч85
Или Обсуждение.Заголовок <> ИсходныйКлюч85 + " | Проверка карточки книги"
Или Обсуждение.Интеграция <> Неопределено Или Обсуждение.КонтекстОбсуждения <> Неопределено
Или Обсуждение.ВнешнийИдентификатор <> ""
Или Обсуждение.Участники.Количество() <> 1 Или Не Обсуждение.Участники.Содержит(Пользователь.Идентификатор) Тогда
ВызватьИсключение "Источник не является собственным закрытым учебным обсуждением";
КонецЕсли;
Отбор = Новый ОтборСообщенийСистемыВзаимодействия;
Отбор.Обсуждение = Обсуждение.Идентификатор;
Отбор.Количество = 3;
Список = СистемаВзаимодействия.ПолучитьСообщения(Отбор);
Если Список.Количество() <> 2 Тогда
ВызватьИсключение "Источник должен содержать ровно две собственные учебные карточки";
КонецЕсли;
Первая = Неопределено;
Вторая = Неопределено;
Для Каждого Карточка Из Список Цикл
Если Карточка.Обсуждение <> Обсуждение.Идентификатор Или Карточка.Автор <> Пользователь.Идентификатор
Или Карточка.Данные <> ИсходныйКлюч85 + "|Книга|3|250" Или Карточка.ФорматДанныхСтроки <> "text/plain"
Или Карточка.Вложения.Количество() <> 0 Или Карточка.Действия.Количество() <> 0 Тогда
ВызватьИсключение "Паспорт одной из собственных карточек неверен";
КонецЕсли;
Если Карточка.ИсходноеСообщение = Неопределено Тогда
Если Первая <> Неопределено Или Строка(Карточка.Текст) <> ИсходныйКлюч85 + " | Книга: количество 3, цена 250" Тогда
ВызватьИсключение "Первая собственная карточка не подтверждена";
КонецЕсли;
Первая = Карточка;
Иначе
Если Вторая <> Неопределено Тогда
ВызватьИсключение "Лишний ответ не допускается";
КонецЕсли;
Текст = Строка(Карточка.Текст);
Если Текст <> ИсходныйКлюч85 + " | Проверка подтверждена: 750"
И (ИсходныйТекст Или Текст <> ИсходныйКлюч85 + " | После выгрузки: 999") Тогда
ВызватьИсключение "Второй собственный текст не совпал с подготовленным опытом";
КонецЕсли;
Вторая = Карточка;
КонецЕсли;
КонецЦикла;
Если Первая = Неопределено Или Вторая = Неопределено Или Вторая.ИсходноеСообщение <> Первая.Идентификатор Тогда
ВызватьИсключение "Связь собственного ответа не подтверждена";
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ИзменитьТолькоСвоюКарточкуПередВосстановлением85()
ПроверитьСвоиДанныеНаСервере85(Истина);
Обсуждение = СистемаВзаимодействия.ПолучитьОбсуждение(ИсходныйКлюч85);
Отбор = Новый ОтборСообщенийСистемыВзаимодействия;
Отбор.Обсуждение = Обсуждение.Идентификатор;
Отбор.Количество = 3;
Для Каждого Карточка Из СистемаВзаимодействия.ПолучитьСообщения(Отбор) Цикл
Если Карточка.ИсходноеСообщение <> Неопределено Тогда
Карточка.Текст = Новый ФорматированнаяСтрока(ИсходныйКлюч85 + " | После выгрузки: 999");
Карточка.Записать();
ПроверитьСвоиДанныеНаСервере85(Ложь);
ПровереннаяКарточка = СистемаВзаимодействия.ПолучитьСообщение(Карточка.Идентификатор);
Если ПровереннаяКарточка.Идентификатор <> Карточка.Идентификатор
Или Строка(ПровереннаяКарточка.Текст) <> ИсходныйКлюч85 + " | После выгрузки: 999" Тогда
ВызватьИсключение "Собственная новая карточка999 не подтверждена перед началом восстановления";
КонецЕсли;
Возврат;
КонецЕсли;
КонецЦикла;
ВызватьИсключение "Своя карточка для изменения не найдена";
КонецПроцедуры
&НаСервере
Функция ПроверитьСвоегоПользователя85()
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Входной привилегированный режим не допускается";
КонецЕсли;
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователи.Количество() <> 1 Или Текущий = Неопределено Тогда
ВызватьИсключение "Нужен единственный собственный учебный пользователь";
КонецЕсли;
Если Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор
Или Лев(Текущий.Имя, СтрДлина("Уч85Связь_")) <> "Уч85Связь_" Тогда
ВызватьИсключение "Учебный пользователь не подтвержден";
КонецЕсли;
UUIDМетки = Новый УникальныйИдентификатор(Сред(Текущий.Имя, СтрДлина("Уч85Связь_") + 1));
Если Текущий.Имя <> "Уч85Связь_" + Строка(UUIDМетки)
Или UUIDМетки = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000") Тогда
ВызватьИсключение "Имя должно содержать собственный канонический ненулевой UUID";
КонецЕсли;
Если Не СистемаВзаимодействия.ИнформационнаяБазаЗарегистрирована()
Или Не СистемаВзаимодействия.ИспользованиеДоступно() Тогда
ВызватьИсключение "Вручную подготовьте регистрацию собственной учебной базы";
КонецЕсли;
Если СистемаВзаимодействия.АдресСервера() <> "http://localhost:9094" Тогда
ВызватьИсключение "Разрешен только отдельно подготовленный сервер localhost:9094 в своей VM";
КонецЕсли;
Версия = СистемаВзаимодействия.ВерсияСервера();
Если ТипЗнч(Версия) <> Тип("Строка") Или Не ЗначениеЗаполнено(Версия) Тогда
ВызватьИсключение "Версия своего сервера не получена";
КонецЕсли;
ИД = СистемаВзаимодействия.ИдентификаторТекущегоПользователя();
Если ТипЗнч(ИД) <> Тип("ИдентификаторПользователяСистемыВзаимодействия") Тогда
ВызватьИсключение "Не получен реальный идентификатор собственного участника";
КонецЕсли;
Если СистемаВзаимодействия.ПолучитьИдентификаторПользователя(Текущий.УникальныйИдентификатор) <> ИД
Или СистемаВзаимодействия.ПолучитьИдентификаторПользователяИнформационнойБазы(ИД) <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Двустороннее соответствие своей учетной записи неверно";
КонецЕсли;
Пользователь = СистемаВзаимодействия.ПолучитьПользователя(ИД);
Если Пользователь.Идентификатор <> ИД Или Пользователь.Имя <> Текущий.Имя
Или Пользователь.ПолноеИмя <> Текущий.ПолноеИмя
Или Пользователь.ИдентификаторПользователяИнформационнойБазы <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Паспорт своего пользователя не совпал с информационной базой";
КонецЕсли;
Если Пользователь.Внешний Или Пользователь.Заблокирован
Или Пользователь.ТипВнешнейСистемы <> ""
Или Пользователь.ИдентификаторПользователяВнешнейСистемы <> Неопределено
Или Пользователь.АдресЭлектроннойПочты <> ""
Или Пользователь.АдресЭлектроннойПочтыДляАутентификации <> ""
Или Пользователь.НомерТелефона <> ""
Или Пользователь.КлючСопоставления <> "" Тогда
ВызватьИсключение "Нужен чистый внутренний пользователь без персональных контактов и объединений";
КонецЕсли;
Если Пользователь.АдминистраторАбонента <> СистемаВзаимодействия.ТекущийПользовательЯвляетсяАдминистраторомАбонента() Тогда
ВызватьИсключение "Признак администратора абонента не согласован";
КонецЕсли;
ВсеПользователи = СистемаВзаимодействия.СтандартныеПользователи.ВсеПользователиПриложения;
Если ИД = ВсеПользователи Или ИД = Новый ИдентификаторПользователяСистемыВзаимодействия Тогда
ВызватьИсключение "Стандартный адресат и Никого не оповещать не являются своей учетной записью";
КонецЕсли;
ВосстановленныйИД = Новый ИдентификаторПользователяСистемыВзаимодействия(Строка(ИД));
Если СистемаВзаимодействия.ПолучитьПользователя(ВосстановленныйИД).Идентификатор <> ИД Тогда
ВызватьИсключение "Восстановленный из строки реальный ID не подтвержден сервером";
КонецЕсли;
Приложение = СистемаВзаимодействия.ПолучитьПриложение(СистемаВзаимодействия.ИдентификаторТекущегоПриложения());
Если Приложение.Идентификатор <> СистемаВзаимодействия.ИдентификаторТекущегоПриложения()
Или Приложение.Наименование <> "УчебноеВзаимодействие85" Тогда
ВызватьИсключение "Нужно свое приложение с точным учебным наименованием";
КонецЕсли;
Возврат Пользователь;
КонецФункции
&НаСервере
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедурыПолный серверный подготовительный модуль УчебноеВзаимодействие: создать собственный чат/две карточки
Общий модуль УчебноеВзаимодействие: полный серверный модуль
Серверный общий модуль своей отдельной CF УчебноеВзаимодействие85; собственный localhost сервер, один UUID-пользователь и две реальные собственные карточки. Не вызывается при авторстве.
Процедура ВыполнитьПример(Подтверждение = "") Экспорт
Пользователь = ПроверитьСвоегоПользователя85();
Если Подтверждение <> "СВОЕ ОБСУЖДЕНИЕ И ДВА СООБЩЕНИЯ" Тогда
ВызватьИсключение "Сначала прочитайте подготовку. Обсуждение не создано";
КонецЕсли;
ИДПользователя = Пользователь.Идентификатор;
Ключ = "Уч85Обсуждение_" + Строка(Новый УникальныйИдентификатор);
Сообщить("Собственный кандидат ключа: " + Ключ);
Если СистемаВзаимодействия.ПолучитьОбсуждение(Ключ) <> Неопределено Тогда
ВызватьИсключение "Коллизия ключа: существующее обсуждение не меняется";
КонецЕсли;
Выбор = Новый КоллекцияИдентификаторовПользователейСистемыВзаимодействия;
Выбор.Добавить(ИДПользователя);
Если Выбор.Количество() <> 1 Или Не Выбор.Содержит(ИДПользователя) Тогда
ВызватьИсключение "Состав своего участника не собран";
КонецЕсли;
Выбор.Удалить(ИДПользователя);
Если Выбор.Количество() <> 0 Или Выбор.Содержит(ИДПользователя) Тогда
ВызватьИсключение "Удаление из локального подбора не подтверждено";
КонецЕсли;
Выбор.Добавить(ИДПользователя);
Выбор.Очистить();
Если Выбор.Количество() <> 0 Тогда
ВызватьИсключение "Локальный подбор не очищен";
КонецЕсли;
Выбор.Добавить(ИДПользователя);
Обсуждение = СистемаВзаимодействия.СоздатьОбсуждение();
Обсуждение.Ключ = Ключ;
Обсуждение.Заголовок = Ключ + " | Проверка карточки книги";
Обсуждение.Групповое = Истина;
Обсуждение.Отображаемое = Истина;
Обсуждение.ТолькоПросмотр = Ложь;
Обсуждение.КонтекстОбсуждения = Неопределено;
Обсуждение.Интеграция = Неопределено;
Обсуждение.ВнешнийИдентификатор = "";
Для Каждого Участник Из Выбор Цикл
Обсуждение.Участники.Добавить(Участник);
КонецЦикла;
Обсуждение.Записать();
ИДОбсуждения = Обсуждение.Идентификатор;
Если ТипЗнч(ИДОбсуждения) <> Тип("ИдентификаторОбсужденияСистемыВзаимодействия") Тогда
ВызватьИсключение "Запись могла произойти, но реальный ID обсуждения не получен";
КонецЕсли;
Сообщить("Свой ID обсуждения: " + Строка(ИДОбсуждения));
Восстановленное = Новый ИдентификаторОбсужденияСистемыВзаимодействия(Строка(ИДОбсуждения));
ПроверитьСвоеОбсуждение85(Восстановленное, Ключ, ИДПользователя);
Отбор = Новый ОтборОбсужденийСистемыВзаимодействия;
Отбор.Ключ = Ключ;
Отбор.Групповое = Истина;
Отбор.Отображаемое = Истина;
Отбор.КонтекстноеОбсуждение = Ложь;
Отбор.КонтекстОбсуждения = Неопределено;
Отбор.ТекущийПользовательЯвляетсяУчастником = Истина;
Отбор.Количество = 2;
Отбор.НаправлениеСортировки = НаправлениеСортировки.Возр;
Отбор.ДатаНачала = Неопределено;
Отбор.ВнешнийИдентификатор = "";
Если Отбор.Интеграция <> Неопределено Тогда
ВызватьИсключение "Новый отбор не должен выбирать внешнюю интеграцию";
КонецЕсли;
Список = СистемаВзаимодействия.ПолучитьОбсуждения(Отбор);
Если Список.Количество() <> 1 Или Список[0].Идентификатор <> ИДОбсуждения Тогда
ВызватьИсключение "Точный отбор собственного обсуждения не совпал";
КонецЕсли;
СистемаВзаимодействия.УстановитьРежимНаблюдения(ИДОбсуждения, Ложь, ИДПользователя);
СистемаВзаимодействия.УстановитьОтображениеОповещенийОбсуждения(ИДОбсуждения,
ОтображениеОповещенийСистемыВзаимодействия.НеБеспокоить, ИДПользователя);
Если СистемаВзаимодействия.ПолучитьРежимНаблюдения(ИДОбсуждения, ИДПользователя)
Или СистемаВзаимодействия.ПолучитьОтображениеОповещенийОбсуждения(ИДОбсуждения, ИДПользователя)
<> ОтображениеОповещенийСистемыВзаимодействия.НеБеспокоить Тогда
ВызватьИсключение "Собственные настройки оповещений не подтверждены";
КонецЕсли;
ПроверитьСвоеОбсуждение85(ИДОбсуждения, Ключ, ИДПользователя);
ОтборДоЗаписи = Новый ОтборСообщенийСистемыВзаимодействия;
ОтборДоЗаписи.Обсуждение = ИДОбсуждения;
ОтборДоЗаписи.Количество = 2;
ОтборДоЗаписи.НаправлениеСортировки = НаправлениеСортировки.Возр;
ОтборДоЗаписи.После = Неопределено;
Если СистемаВзаимодействия.ПолучитьСообщения(ОтборДоЗаписи).Количество() <> 0 Тогда
ВызватьИсключение "Перед первой своей записью обсуждение должно быть пусто";
КонецЕсли;
Исходное = СистемаВзаимодействия.СоздатьСообщение(ИДОбсуждения);
Исходное.Текст = Новый ФорматированнаяСтрока(Ключ + " | Книга: количество 3, цена 250");
Исходное.Данные = Ключ + "|Книга|3|250";
Исходное.ФорматДанныхСтроки = "text/plain";
Исходное.Получатели.Добавить(Новый ИдентификаторПользователяСистемыВзаимодействия);
ПроверитьСвойЧерновик85(Исходное);
Исходное.Записать();
ИДИсходного = Исходное.Идентификатор;
Сообщить("Свой ID первого сообщения: " + Строка(ИДИсходного));
ПервыйФакт = СистемаВзаимодействия.ПолучитьСообщение(
Новый ИдентификаторСообщенияСистемыВзаимодействия(Строка(ИДИсходного)));
ПроверитьСвоеСообщение85(ПервыйФакт, ИДИсходного, ИДОбсуждения, ИДПользователя, Ключ,
Ключ + " | Книга: количество 3, цена 250", Неопределено);
ПроверитьСвоеОбсуждение85(ИДОбсуждения, Ключ, ИДПользователя);
ДоВторойЗаписи = СистемаВзаимодействия.ПолучитьСообщения(ОтборДоЗаписи);
Если ДоВторойЗаписи.Количество() <> 1 Или ДоВторойЗаписи[0].Идентификатор <> ИДИсходного Тогда
ВызватьИсключение "Перед второй своей записью ожидается только подтвержденное первое сообщение";
КонецЕсли;
Второе = СистемаВзаимодействия.СоздатьСообщение(ИДОбсуждения);
Второе.Текст = Новый ФорматированнаяСтрока(Ключ + " | Проверка: сумма 750");
Второе.Данные = Ключ + "|Книга|3|250";
Второе.ФорматДанныхСтроки = "text/plain";
Второе.ИсходноеСообщение = ИДИсходного;
Второе.Получатели.Добавить(Новый ИдентификаторПользователяСистемыВзаимодействия);
ПроверитьСвойЧерновик85(Второе);
Второе.Записать();
ИДВторого = Второе.Идентификатор;
Сообщить("Свой ID второго сообщения: " + Строка(ИДВторого));
ВторойФакт = СистемаВзаимодействия.ПолучитьСообщение(ИДВторого);
ПроверитьСвоеСообщение85(ВторойФакт, ИДВторого, ИДОбсуждения, ИДПользователя, Ключ,
Ключ + " | Проверка: сумма 750", ИДИсходного);
ПроверитьСвойСписок85(ИДОбсуждения, ИДИсходного, ИДВторого);
ПроверитьСвоеОбсуждение85(ИДОбсуждения, Ключ, ИДПользователя);
ВторойФакт = СистемаВзаимодействия.ПолучитьСообщение(ИДВторого);
ПроверитьСвоеСообщение85(ВторойФакт, ИДВторого, ИДОбсуждения, ИДПользователя, Ключ,
Ключ + " | Проверка: сумма 750", ИДИсходного);
ВторойФакт.Текст = Новый ФорматированнаяСтрока(Ключ + " | Проверка подтверждена: 750");
ВторойФакт.Записать();
ПроверитьСвоеСообщение85(СистемаВзаимодействия.ПолучитьСообщение(ИДВторого),
ИДВторого, ИДОбсуждения, ИДПользователя, Ключ,
Ключ + " | Проверка подтверждена: 750", ИДИсходного);
Сообщить("Два своих сообщения сохранены, отобраны и одно обновлено. Удаление не выполняется автоматически");
КонецПроцедуры
Процедура ПроверитьСвойЧерновик85(Сообщение)
Если Сообщение.Вложения.Количество() <> 0 Или Сообщение.Действия.Количество() <> 0
Или Сообщение.ПанельКнопок.РядыКнопок.Количество() <> 0
Или Сообщение.ЗначенияПодстановокШаблонаСообщения.Количество() <> 0
Или Сообщение.ШаблонСообщения <> Неопределено Тогда
ВызватьИсключение "Новый собственный черновик содержит неподготовленные вложения или шаблон";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоеОбсуждение85(Идентификатор, Ключ, Участник)
Факт = СистемаВзаимодействия.ПолучитьОбсуждение(Идентификатор);
Если Факт.Идентификатор <> Идентификатор Или Факт.Ключ <> Ключ
Или Факт.Заголовок <> Ключ + " | Проверка карточки книги"
Или Не Факт.Групповое Или Не Факт.Отображаемое Или Факт.ТолькоПросмотр
Или Факт.КонтекстОбсуждения <> Неопределено Или Факт.Интеграция <> Неопределено
Или Факт.ВнешнийИдентификатор <> ""
Или Факт.Участники.Количество() <> 1 Или Не Факт.Участники.Содержит(Участник) Тогда
ВызватьИсключение "Полный собственный паспорт обсуждения изменен или не совпал";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоеСообщение85(Факт, Идентификатор, Обсуждение, Автор, Ключ, Текст, Исходное)
Если Факт.Идентификатор <> Идентификатор Или Факт.Обсуждение <> Обсуждение
Или Факт.Автор <> Автор Или Строка(Факт.Текст) <> Текст
Или Факт.Данные <> Ключ + "|Книга|3|250" Или Факт.ФорматДанныхСтроки <> "text/plain"
Или Факт.ИсходноеСообщение <> Исходное Или ТипЗнч(Факт.Дата) <> Тип("Дата")
Или Факт.Дата = Дата(1, 1, 1) Тогда
ВызватьИсключение "Полное собственное сообщение не подтверждено. Чужое содержимое не выводится";
КонецЕсли;
ПроверитьСвойЧерновик85(Факт);
КонецПроцедуры
Процедура ПроверитьСвойСписок85(Обсуждение, Первый, Второй)
Отбор = Новый ОтборСообщенийСистемыВзаимодействия;
Отбор.Обсуждение = Обсуждение;
Отбор.Количество = 3;
Отбор.НаправлениеСортировки = НаправлениеСортировки.Возр;
Отбор.После = Неопределено;
Список = СистемаВзаимодействия.ПолучитьСообщения(Отбор);
Если Список.Количество() <> 2 Тогда
ВызватьИсключение "В собственном обсуждении должно быть ровно два собственных сообщения";
КонецЕсли;
Для Каждого СтрокаСообщения Из Список Цикл
Если СтрокаСообщения.Обсуждение <> Обсуждение
Или СтрокаСообщения.Идентификатор <> Первый И СтрокаСообщения.Идентификатор <> Второй Тогда
ВызватьИсключение "В список попало неподтвержденное сообщение";
КонецЕсли;
КонецЦикла;
Отбор.После = Второй;
Если СистемаВзаимодействия.ПолучитьСообщения(Отбор).Количество() <> 0 Тогда
ВызватьИсключение "После второго собственного сообщения не ожидаются записи";
КонецЕсли;
КонецПроцедуры
Функция ПроверитьСвоегоПользователя85()
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Входной привилегированный режим не допускается";
КонецЕсли;
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователи.Количество() <> 1 Или Текущий = Неопределено Тогда
ВызватьИсключение "Нужен единственный собственный учебный пользователь";
КонецЕсли;
Если Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор
Или Лев(Текущий.Имя, СтрДлина("Уч85Связь_")) <> "Уч85Связь_" Тогда
ВызватьИсключение "Учебный пользователь не подтвержден";
КонецЕсли;
UUIDМетки = Новый УникальныйИдентификатор(Сред(Текущий.Имя, СтрДлина("Уч85Связь_") + 1));
Если Текущий.Имя <> "Уч85Связь_" + Строка(UUIDМетки)
Или UUIDМетки = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000") Тогда
ВызватьИсключение "Имя должно содержать собственный канонический ненулевой UUID";
КонецЕсли;
Если Не СистемаВзаимодействия.ИнформационнаяБазаЗарегистрирована()
Или Не СистемаВзаимодействия.ИспользованиеДоступно() Тогда
ВызватьИсключение "Вручную подготовьте регистрацию собственной учебной базы";
КонецЕсли;
Если СистемаВзаимодействия.АдресСервера() <> "http://localhost:9094" Тогда
ВызватьИсключение "Разрешен только отдельно подготовленный сервер localhost:9094 в своей VM";
КонецЕсли;
Версия = СистемаВзаимодействия.ВерсияСервера();
Если ТипЗнч(Версия) <> Тип("Строка") Или Не ЗначениеЗаполнено(Версия) Тогда
ВызватьИсключение "Версия своего сервера не получена";
КонецЕсли;
ИД = СистемаВзаимодействия.ИдентификаторТекущегоПользователя();
Если ТипЗнч(ИД) <> Тип("ИдентификаторПользователяСистемыВзаимодействия") Тогда
ВызватьИсключение "Не получен реальный идентификатор собственного участника";
КонецЕсли;
Если СистемаВзаимодействия.ПолучитьИдентификаторПользователя(Текущий.УникальныйИдентификатор) <> ИД
Или СистемаВзаимодействия.ПолучитьИдентификаторПользователяИнформационнойБазы(ИД) <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Двустороннее соответствие своей учетной записи неверно";
КонецЕсли;
Пользователь = СистемаВзаимодействия.ПолучитьПользователя(ИД);
Если Пользователь.Идентификатор <> ИД Или Пользователь.Имя <> Текущий.Имя
Или Пользователь.ПолноеИмя <> Текущий.ПолноеИмя
Или Пользователь.ИдентификаторПользователяИнформационнойБазы <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Паспорт своего пользователя не совпал с информационной базой";
КонецЕсли;
Если Пользователь.Внешний Или Пользователь.Заблокирован
Или Пользователь.ТипВнешнейСистемы <> ""
Или Пользователь.ИдентификаторПользователяВнешнейСистемы <> Неопределено
Или Пользователь.АдресЭлектроннойПочты <> ""
Или Пользователь.АдресЭлектроннойПочтыДляАутентификации <> ""
Или Пользователь.НомерТелефона <> ""
Или Пользователь.КлючСопоставления <> "" Тогда
ВызватьИсключение "Нужен чистый внутренний пользователь без персональных контактов и объединений";
КонецЕсли;
Если Пользователь.АдминистраторАбонента <> СистемаВзаимодействия.ТекущийПользовательЯвляетсяАдминистраторомАбонента() Тогда
ВызватьИсключение "Признак администратора абонента не согласован";
КонецЕсли;
ВсеПользователи = СистемаВзаимодействия.СтандартныеПользователи.ВсеПользователиПриложения;
Если ИД = ВсеПользователи Или ИД = Новый ИдентификаторПользователяСистемыВзаимодействия Тогда
ВызватьИсключение "Стандартный адресат и Никого не оповещать не являются своей учетной записью";
КонецЕсли;
ВосстановленныйИД = Новый ИдентификаторПользователяСистемыВзаимодействия(Строка(ИД));
Если СистемаВзаимодействия.ПолучитьПользователя(ВосстановленныйИД).Идентификатор <> ИД Тогда
ВызватьИсключение "Восстановленный из строки реальный ID не подтвержден сервером";
КонецЕсли;
Приложение = СистемаВзаимодействия.ПолучитьПриложение(СистемаВзаимодействия.ИдентификаторТекущегоПриложения());
Если Приложение.Идентификатор <> СистемаВзаимодействия.ИдентификаторТекущегоПриложения()
Или Приложение.Наименование <> "УчебноеВзаимодействие85" Тогда
ВызватьИсключение "Нужно свое приложение с точным учебным наименованием";
КонецЕсли;
Возврат Пользователь;
КонецФункции
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедурыРазбор по шагам
Главный guard подтверждает свой единственный UUID-пользователь/точный localhost/точное приложение. Подготовительный ключ должен быть каноническим UUID, а чат — без контекста/интеграции/внешних привязок, с одним собственным участником. Ровно две карточки имеют свой автор/данные/MIME/точные исходные тексты и настоящую связь ответа.
Безаргументный ПолучитьВыгрузкуДанных() в серверном модуле возвращает Массив списка. Это отдельная native-перегрузка от ПолучитьВыгрузкуДанных(ИД), которая возвращает один объект. Exporter-суффикс #&^@^%&*^#1 не является BSL именем и нигде в коде не вызывается.
Создать85 проверяет отсутствие прежних файлов и устанавливает НеизвестныйИсход до начала. Синхронная ветвь возвращает настоящий ID; Ждать НачатьСозданиеВыгрузкиДанныхАсинх тоже возвращает ID при НАЧАЛЕ создания. Ни возврат native-вызова, ни выполнение обещания не означают готового файла.
IDВыгрузки85 содержит только Строка ID, реально возвращенного созданием. Для дальнейших команд конструктор получает именно эту строку; она не создается из произвольного UUID/чужого ввода. Get по ID проверяет настоящий объект, тот же ID, свою точную Описание, серверную дату в часовом поясе сеанса и тип ДоступнаВыгрузка.
Проверить85 читает status без автоматического повторения. Создание/Восстановление — ожидание, Ошибка — отказ, Загрузка — неожиданный чужой для этого опыта путь, Готово — только готовность файла. СтатусВосстановления=Неопределено может означать неначатый ИЛИ незавершенный процесс, поэтому его нельзя использовать как доказательство отсутствия восстановления.
GetAddress вызывается только для готового своего ID. ДоступнаВыгрузка=true требует точную локальную S3-ссылку; false допускает только полученный серверный файловый путь, не публичный URL. Сам адрес/подписанный query не выводятся в журналы или интерфейс, HTTP/file операции не выполняются. Получение адреса — не скачивание и не проверка содержимого файла.
Описание85 меняет описание только своим API УстановитьОписаниеВыгрузкиДанных, не присваиванием readonly свойства. После native-ответа получаются fresh ID/Описание; новое значение формируется только из собственной метки. Promise setter заканчивается Неопределено, а не Булево успеха.
Восстановить85 свежо подтверждает собственные исходные карточки и меняет только свой второй текст750 на999. НачатоВосстановление и возможная запись отмечены заранее. Затем синхронный begin или Ждать BeginRestore начинают восстановление своего ID, но не объявляют окончания; promise-result=Неопределено.
Проверить85 после begin требует одновременно Готово, СтатусВосстановления=Успешно и fresh проверку двух исходных карточек750/их данных/автора/связи ответа. Одно enumУспешно не заменяет содержательную проверку; ошибка/неизвестное состояние не дают разрешения удалить файл.
Удалить85 требует свежую готовую свою выгрузку, известное состояние и точное повторное подтверждение своего ID. Для серверной ветви guard повторяется на сервере, для Ждать результат Неопределено отдельно проверяется. После удаления свежий список в изначально пустом приложении должен быть пуст. Catch не пытается восстановить удаленный файл.
В catch снимается только флаг выполняющейся команды, но НеизвестныйИсход не снимается. Программа не пишет повторно, не удаляет/откатывает в обработчике ошибки и не выводит адреса/ключи/чужие тексты. Ручная сверка допустима только по собственным метке/ID на своем отдельном сервере.
Как проверить результат
До создания и без фразы нет записей. Непустой прежний список, другой участник/автор/данные или третья карточка должны остановить опыт до начала выгрузки.
После Создать85 показан только фактический ID начатого процесса, не обещание готовности. Попытка изменить/восстановить/удалить до ручного подтверждения Готово должна отказать.
Проверить85 показывает собственные состояния без плотного polling. Readonly дата/ID/описание/ДоступнаВыгрузка/статусы читаются, не назначаются. Полученный серверный путь не принимается за файл клиента1С.
После изменения описания fresh Get подтверждает тот же свой ID и точное новое описание. После beginrestore возврат метода не показывает восстановление.
Положительный результат восстановления требует свежей исходной карточки750 вместо999, исходных данных и связи с первой карточкой, плюс nativeУспешно. Неопределено/Ошибка/неожиданный процесс не считаются успехом.
Без точного подтверждения ID удаление не вызывается. После подтвержденного удаления список пуст, фаза Удалено, дальнейшие операции запрещены. Потерянный ответ не разрешает повторное удаление автоматически.
Ожидаемый результат
Реальный собственный цикл выгрузки/готовности/описания/начала восстановления/проверки двух карточек/удаления дан для server и Ждать. Готовность файла, готовность обещания и подтвержденное восстановление данных различаются; неизвестный результат остается неизвестным.
На что обратить внимание
Файлы выгрузок содержат данные системы взаимодействия, а не файл конфигурации или .dt базы1С. Снимок/восстановление может затронуть все приложение: только выделенная собственная VM/сервер/абонент/приложение без персональных сведений.
Native синхронные методы доступны server/thick/external, promise-методы — client/external по конкретной странице; не переносите Ждать-код на сервер. НачатьСоздание и НачатьВосстановление завершают свою функцию при старте процесса, не при готовности.
ПолучитьВыгрузкуДанных имеет две разные перегрузки: ноль аргументов=Массив списка, реальный ID=один объект. Exporter synthetic suffix — только канонический ключ карточки, не имя метода встроенного языка.
В экспортированном plain-пункте нулевая signature.params/returnTypeDefinition=Массив расходятся с ошибочно обогащенными syntaxText/описанием одного объекта. У sentinel-пункта один обязательный ID и returnTypeDefinition одного объекта. Урок привязан по точным установленным GetDataDumps6305.html и GetDataDump6307.html, не по этому ошибочному тексту exporter; источники/карточки не переписаны.
ID из строки не проверяется конструктором. Его происхождение, exactметка/описание и fresh native-объект проверяются отдельно. Системные статусы и даты не устанавливаются вручную; readonly Описание изменяется только выделенным методом менеджера.
S3-ссылка ограничена по времени и может содержать секретный токен; не публикуйте ее. ДоступнаВыгрузка относится к S3-скачиванию, не к общему статусу готовности. File-путь относится именно к серверу взаимодействия и не обязан существовать на клиенте/сервере1С.
СтатусВосстановления=Неопределено не отличает никогда не начатое восстановление от еще не завершенного. Пульт хранит собственный флаг начала, проверяет основной статус и реальные собственные исходные карточки; при потере формы история ожидания может потеряться.
НеизвестныйИсход после потенциальной записи не очищается чтением и не заменяется сообщением успеха. Восстановление/удаление не атомарны с предварительным чтением; параллельные клиенты/боты/другие администраторы запрещены подготовкой. Нет автоматического undo, retry или восстановления удаленного файла.
Реальные действия автором не выполнялись: server/S3/files не использовались, backup/archive не создан, сеть/данные/права не менялись. Статическая проверка API8.5.1.1343 и кода не равна проверке сервера или восстановлению. RuntimeVerifiedScenarios=0.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.