В собственной транзакции прочитать движение и собрать ключ из сохранённого НомерСтроки

Учебные задачи

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

Где и как запускать

Учебная база: создайте серверный общий модуль УчебныеЗадачи (флаг Сервер). Код без директив вставьте в тело процедуры ВыполнитьПример() Экспорт. Вызовите её из серверного обработчика команды учебной обработки. Не запускайте в рабочей базе.

Подготовка

  1. Создайте НОВУЮ пустую файловую базу, имя корневой конфигурации УчебныеОстатки85. Не добавляйте эти объекты в УТ/КА2/УНФ/БП. Режим управления блокировкой данных конфигурации — Управляемый.

  2. Документы → Добавить: УчебноеДвижение85. Номер: Строка длиной 40, автонумерация выключена. Модули объекта и менеджера оставьте пустыми; не добавляйте обработчики, подписки и обязательные пользовательские реквизиты.

  3. Регистры накопления → Добавить: УчебныеОстатки85. Вид регистра Остатки. Единственное измерение КодТовара: Строка 50, индексировать, проверка заполнения Показывать ошибку. Единственный ресурс Количество: Число 12,3, неотрицательное. Дополнительных реквизитов нет.

  4. В списке регистраторов выберите только собственный документ УчебноеДвижение85. Оставьте модули регистра пустыми, использование итогов включённым. Планы обмена, разделители, историю данных и фоновые задания для урока не создавайте.

  5. Обновите конфигурацию базы данных. Создайте серверный общий модуль УчебныеЗадачи и команду собственной обработки. Фрагмент вставьте внутрь ВыполнитьПример() Экспорт; запускайте задачи по отдельности.

  6. Первые задачи работают с незаписанными наборами. Только задачи с пометкой «в собственной транзакции» временно записывают два собственных документа и движения, затем обязательно отменяют транзакцию. В рабочей базе этот код не запускайте.

  7. Убедитесь, что модули документа и набора записей, подписки и планы обмена действительно пустые: отмена транзакции НЕ отменяет уже отправленные HTTP-запросы, письма или запись внешних файлов.

  8. Запускайте как отдельную серверную команду, не из проведения документа и не внутри чужой транзакции. Здесь нет ЗафиксироватьТранзакцию: временные учебные данные должны исчезнуть.

Если Метаданные.Документы.Количество() <> 1
    Или Метаданные.РегистрыНакопления.Количество() <> 1
    Или Метаданные.Документы.Найти("УчебноеДвижение85") = Неопределено Тогда
    ВызватьИсключение "Разрешены только собственный учебный документ и регистр";
КонецЕсли;
Описание = Метаданные.РегистрыНакопления.Найти("УчебныеОстатки85");
Если Описание = Неопределено Тогда
    ВызватьИсключение "Сначала создайте собственный учебный регистр";
КонецЕсли;
Если Описание.ВидРегистра <> Метаданные.СвойстваОбъектов.ВидРегистраНакопления.Остатки
    Или Описание.Измерения.Количество() <> 1
    Или Описание.Ресурсы.Количество() <> 1
    Или Описание.Реквизиты.Количество() <> 0
    Или Описание.Измерения.Найти("КодТовара") = Неопределено
    Или Описание.Ресурсы.Найти("Количество") = Неопределено Тогда
    ВызватьИсключение "Нужен регистр остатков с КодТовара и Количество";
КонецЕсли;
Менеджер = РегистрыНакопления.УчебныеОстатки85;
Если ТранзакцияАктивна() Тогда
    ВызватьИсключение "Не запускайте урок внутри чужой транзакции";
КонецЕсли;
Если Не Менеджер.ПолучитьИспользованиеИтогов() Тогда
    ВызватьИсключение "В учебном регистре должны быть включены итоги";
КонецЕсли;
Код = "TRAIN-" + Строка(Новый УникальныйИдентификатор);
ОтборТовара = Новый Структура("КодТовара", Код);
Начало = Дата(2026, 9, 15, 0, 0, 0);
Конец = Дата(2026, 9, 16, 0, 0, 0);
НачатьТранзакцию();
Попытка
    ДокументПрихода = Документы.УчебноеДвижение85.СоздатьДокумент();
    ДокументПрихода.Дата = Дата(2026, 9, 15, 10, 0, 0);
    ДокументПрихода.Номер = "P-" + Строка(Новый УникальныйИдентификатор);
    ДокументПрихода.Записать();
    ДокументРасхода = Документы.УчебноеДвижение85.СоздатьДокумент();
    ДокументРасхода.Дата = Дата(2026, 9, 15, 11, 0, 0);
    ДокументРасхода.Номер = "E-" + Строка(Новый УникальныйИдентификатор);
    ДокументРасхода.Записать();

    НаборПрихода = Менеджер.СоздатьНаборЗаписей();
    НаборПрихода.Отбор.Регистратор.Установить(ДокументПрихода.Ссылка);
    Приход = НаборПрихода.ДобавитьПриход();
    Приход.Период = ДокументПрихода.Дата;
    Приход.Регистратор = ДокументПрихода.Ссылка;
    Приход.Активность = Истина;
    Приход.КодТовара = Код;
    Приход.Количество = 3;
    НаборПрихода.Записать(Истина);

    НаборРасхода = Менеджер.СоздатьНаборЗаписей();
    НаборРасхода.Отбор.Регистратор.Установить(ДокументРасхода.Ссылка);
    Расход = НаборРасхода.ДобавитьРасход();
    Расход.Период = ДокументРасхода.Дата;
    Расход.Регистратор = ДокументРасхода.Ссылка;
    Расход.Активность = Истина;
    Расход.КодТовара = Код;
    Расход.Количество = 1;
    НаборРасхода.Записать(Истина);

    Выборка = Менеджер.ВыбратьПоРегистратору(ДокументПрихода.Ссылка);
    Если Не Выборка.Следующий() Тогда
        ВызватьИсключение "Собственное движение прихода не прочитано";
    КонецЕсли;
    Сообщить(Выборка.Регистратор = ДокументПрихода.Ссылка);
    Сообщить(Выборка.Период = ДокументПрихода.Дата);
    Сообщить(Выборка.Активность);
    Сообщить(Выборка.ВидДвижения = ВидДвиженияНакопления.Приход);
    Сообщить(Выборка.НомерСтроки > 0);
    Сообщить(Выборка.КодТовара = Код И Выборка.Количество = 3);
    Прочитанный = Менеджер.СоздатьНаборЗаписей();
    Прочитанный.Отбор.Регистратор.Установить(ДокументПрихода.Ссылка);
    Прочитанный.Прочитать();
    Если Прочитанный.Количество() <> 1 Тогда
        ВызватьИсключение "Ожидалась одна строка собственного прихода";
    КонецЕсли;
    СтрокаНабора = Прочитанный.Получить(0);
    Сообщить(СтрокаНабора.НомерСтроки = Выборка.НомерСтроки);
    Ключ = Менеджер.СоздатьКлючЗаписи(Новый Структура("Регистратор,НомерСтроки", СтрокаНабора.Регистратор, СтрокаНабора.НомерСтроки));
    Сообщить(Ключ.Регистратор = Выборка.Регистратор И Ключ.НомерСтроки = Выборка.НомерСтроки);
    Сообщить(Не Выборка.Следующий());
    ВсеПоКоду = Менеджер.Выбрать(Начало, Конец, ОтборТовара, "Возр");
    ЧислоДвижений = 0;
    ДляВыборкиОстаток = 0;
    Пока ВсеПоКоду.Следующий() Цикл
        ЧислоДвижений = ЧислоДвижений + 1;
        Если ВсеПоКоду.ВидДвижения = ВидДвиженияНакопления.Приход Тогда
            ДляВыборкиОстаток = ДляВыборкиОстаток + ВсеПоКоду.Количество;
        Иначе
            ДляВыборкиОстаток = ДляВыборкиОстаток - ВсеПоКоду.Количество;
        КонецЕсли;
    КонецЦикла;
    Сообщить(ЧислоДвижений = 2 И ДляВыборкиОстаток = 2);
    ОтменитьТранзакцию();
Исключение
    Если ТранзакцияАктивна() Тогда
        ОтменитьТранзакцию();
    КонецЕсли;
    ВызватьИсключение;
КонецПопытки;
Сообщить(Не ТранзакцияАктивна());
ПослеОтмены = Менеджер.Выбрать(Начало, Конец, ОтборТовара);
Сообщить(Не ПослеОтмены.Следующий());
Сообщить("Временные движения отменены. Учебная транзакция завершена.");

Разбор по шагам

  1. В собственной транзакции записываем приход и расход на два отдельных своих документа. Чужие регистраторы не используются.

  2. ВыбратьПоРегистратору ограничивает чтение документом прихода. Поля читаются только после успешного Следующий.

  3. Проверяем период, регистратор, активность, направление и положительный постоянный номер строки.

  4. Прочитать набора с тем же отбором возвращает одну строку. Получить(0) — доступ по индексу, НомерСтроки — ключ сохранённой записи.

  5. СоздатьКлючЗаписи получает номер из прочитанной строки. Выбрать с одним индексируемым измерением читает два движения собственного кода.

  6. Все записи отменяются; после отката выборка собственного кода пуста. Номер до отката не остаётся доказательством существования движения.

Как проверить результат

  1. Внутри транзакции десять сообщений Истина, в том числе один приход по регистратору и два движения по коду с остатком 2.

  2. После отмены две проверки Истина: транзакция закрыта, движений этого кода нет.

Ожидаемый результат

Запись выборки, запись набора и ключ связаны через регистратор и постоянный номер, а не через индекс 0.

На что обратить внимание

  1. До первого Следующий или после его Ложь нельзя обращаться к текущей строке выборки.

  2. Отбор для Выбрать допускает только один индексируемый реквизит/измерение; для сложных условий используйте параметризованный запрос.

  3. Не присваивайте НомерСтроки в обычном наборе. Расширенные режимы изменения ключей — отдельная тема, здесь они не включаются.

  4. Все данные урока откатываются. Для рабочего аудита нужны реальные существующие регистраторы и права чтения.

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

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.