РегистрРасчетаМенеджер.<Имя регистра расчета>.Перерасчеты

Свойства · Recalculations

Тип: ПерерасчетыМенеджер.<Имя регистра расчета>. Свойство дает доступ к менеджеру всех перерасчетов регистра расчетов.

Полное описание, параметры и ограничения

РегистрРасчетаМенеджер.<Имя регистра расчета>.Перерасчеты (CalculationRegisterManager.<Calculation register name>.Recalculations)

РегистрРасчетаМенеджер.<Имя регистра расчета> (CalculationRegisterManager.<Calculation register name>)

Перерасчеты (Recalculations)

Доступен, начиная с версии 8.0.

Использование:
Только чтение.
Описание:
Тип: ПерерасчетыМенеджер.<Имя регистра расчета>.
Свойство дает доступ к менеджеру всех перерасчетов регистра расчетов.
Доступность:

Сервер, толстый клиент, внешнее соединение.

Использование в версии:

Доступен, начиная с версии 8.0.

Методическая информация

Практические примеры

Создать свой черновой набор перерасчёта и проверить три записи по индексам

Подготовленный собственный менеджер создаёт действительно пустой набор. Добавляем три свои строки A,B,C с явно пустыми ссылочными ключами и различаем индексы 0..2 от результата -1 для записи другого собственного набора.

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

Полный серверный общий модуль УчебныйНаборПерерасчета85 собственной новой конфигурации УчебныйПерерасчет85. Все помощники предоставлены; отдельная полная форма запуска дана в подготовке/supportingModules. Запуск в 1С здесь не проверялся.

Подготовка

  1. Создайте НОВУЮ отдельную пустую учебную информационную базу на точной 8.5.1.1343 и конфигурацию УчебныйПерерасчет85. Не используйте рабочую базу или расширение готовой конфигурации. Никаких подписок, общих реквизитов, иных регистров, справочников или документов.

  2. Конфигуратор → Планы видов расчета → новый УчебныеВидыПерерасчета85. Использование периода действия=Нет; Зависимость от видов расчета=Не использовать; список базовых планов пуст. Без собственных реквизитов/табличных частей, предопределённых видов и кода модулей.

  3. Конфигуратор → Регистры расчета → новый УчебныйРегистрПерерасчета85. План видов расчета=УчебныеВидыПерерасчета85, периодичность=Месяц, Период действия=Нет, Базовый период=Нет. График не назначайте. Модули менеджера и набора записей пустые.

  4. У своего регистра единственное измерение Ключ85: единственный тип Строка, длина 20, допустимая длина Переменная. Единственный ресурс Результат85: единственный тип Число, длина 12, точность 2, допустимый знак Любой. Собственных реквизитов нет.

  5. У регистра → Перерасчеты → новый Очередь85 → Измерения → единственный Ключ85. В свойстве Измерение регистра выберите именно измерение Ключ85 родительского УчебныйРегистрПерерасчета85. Данные ведущих регистров пусты. Модуль набора записей перерасчета пуст.

  6. Конфигуратор → Документы → новый УчебныйРегистраторПерерасчета85. Проведение=Разрешить; в Движения включите только УчебныйРегистрПерерасчета85. Собственных реквизитов и табличных частей нет. Все объектные/менеджерские модули пустые; не создавайте документ и не проводите его.

  7. Остальные объектные модули, модули приложения и сеанса оставьте пустыми; не подключайте расширений, внешних обработчиков или подписок. Предопределённых элементов плана не создавайте. После ручной подготовки выполните проверку конфигурации и обновление учебной конфигурации базы. Здесь такая конфигурация и 1С не запускались.

  8. Все три поля каждой своей строки: ОбъектПерерасчета — пустая ссылка именно своего документа; ВидРасчета — пустая ссылка именно своего плана; Ключ85 — собственная строка 1..20. Пустые ссылки означают незаполненные учебные ключи, не существующие документы/виды и не готовые к записи данные.

  9. Конфигуратор → Общие → Общие модули → УчебныйНаборПерерасчета85. Создайте отдельный неглобальный серверный общий модуль: Сервер=Да, Вызов сервера=Нет, Привилегированный=Нет, оба клиентских флага и внешнее соединение=Нет, повторное использование возвращаемых значений=Не использовать. Весь основной код вставьте на уровне этого модуля, не внутрь иной процедуры.

  10. Для ЭТОГО урока создайте собственную новую внешнюю обработку УчебныйПускПерерасчета85 с управляемой формой Форма, командой Выполнить и её кнопкой. Полный отдельный модуль формы ниже; не смешивайте его директивы с серверным общим модулем. Для другого урока используйте его собственный модуль формы и общее имя из соответствующей подготовки:

    &НаКлиенте
    Процедура Выполнить(Команда)
    ВыполнитьНаСервере();
    Сообщить("Учебный опыт завершен без записи набора в базу");
    КонецПроцедуры

    &НаСервереБезКонтекста
    Процедура ВыполнитьНаСервере()
    УчебныйНаборПерерасчета85.ВыполнитьПример();
    КонецПроцедуры

Процедура ВыполнитьПример() Экспорт
    ПроверитьСвойСтендПерерасчета();
    ОбъектПерерасчета = Документы.УчебныйРегистраторПерерасчета85.ПустаяСсылка();
    ВидРасчета = ПланыВидовРасчета.УчебныеВидыПерерасчета85.ПустаяСсылка();
    ПроверитьСвоиСсылки(ОбъектПерерасчета, ВидРасчета);
    Набор = СоздатьСвойПустойНабор();
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи(), ОбъектПерерасчета, ВидРасчета);
    ПроверитьСвойКлюч("A");
    ПроверитьСвойКлюч("12345678901234567890");
    ПроверитьНеверныйСвойКлюч(Неопределено);
    ПроверитьНеверныйСвойКлюч(1);
    ПроверитьНеверныйСвойКлюч("");
    ПроверитьНеверныйСвойКлюч("123456789012345678901");
    ПроверитьНеверныйСвойИндекс(0, Набор.Количество());
    ЗаписьA = ДобавитьСвоюЗапись(Набор, "A", ОбъектПерерасчета, ВидРасчета);
    ЗаписьB = ДобавитьСвоюЗапись(Набор, "B", ОбъектПерерасчета, ВидРасчета);
    ЗаписьC = ДобавитьСвоюЗапись(Набор, "C", ОбъектПерерасчета, ВидРасчета);
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи("A", "B", "C"), ОбъектПерерасчета, ВидРасчета);
    Если Набор.Индекс(ЗаписьA) <> 0 Или Набор.Индекс(ЗаписьB) <> 1 Или Набор.Индекс(ЗаписьC) <> 2 Тогда
        ВызватьИсключение "Добавленные собственные записи не заняли ожидаемые индексы 0,1,2";
    КонецЕсли;
    ПроверитьСвойИндекс(0, Набор.Количество());
    ПроверитьСвойИндекс(2, Набор.Количество());
    ПроверитьНеверныйСвойИндекс(Неопределено, Набор.Количество());
    ПроверитьНеверныйСвойИндекс("1", Набор.Количество());
    ПроверитьНеверныйСвойИндекс(-1, Набор.Количество());
    ПроверитьНеверныйСвойИндекс(3, Набор.Количество());
    ПроверитьНеверныйСвойИндекс(1.5, Набор.Количество());
    ВторойНабор = СоздатьСвойПустойНабор();
    ДругаяЗапись = ДобавитьСвоюЗапись(ВторойНабор, "D", ОбъектПерерасчета, ВидРасчета);
    Если Набор.Индекс(ДругаяЗапись) <> -1 Или ВторойНабор.Индекс(ДругаяЗапись) <> 0 Тогда
        ВызватьИсключение "Запись собственного другого набора не должна находиться в первом";
    КонецЕсли;
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи("A", "B", "C"), ОбъектПерерасчета, ВидРасчета);
    ПроверитьСвойПолныйПорядок(ВторойНабор, СвоиКлючи("D"), ОбъектПерерасчета, ВидРасчета);
КонецПроцедуры

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

Функция СоздатьСвойПустойНабор()
    Набор = РегистрыРасчета.УчебныйРегистрПерерасчета85.Перерасчеты.Очередь85.СоздатьНаборЗаписей();
    МетаПерерасчет = Метаданные.РегистрыРасчета.УчебныйРегистрПерерасчета85.Перерасчеты.Очередь85;
    Если Набор.Количество() <> 0 Или Набор.Метаданные() <> МетаПерерасчет Тогда
        ВызватьИсключение "Создан не пустой набор своего перерасчета Очередь85";
    КонецЕсли;
    Возврат Набор;
КонецФункции

Функция СвоиКлючи(Первый = Неопределено, Второй = Неопределено, Третий = Неопределено)
    Ключи = Новый Массив;
    Кандидаты = Новый Массив;
    Кандидаты.Добавить(Первый);
    Кандидаты.Добавить(Второй);
    Кандидаты.Добавить(Третий);
    Для Каждого Ключ Из Кандидаты Цикл
        Если ТипЗнч(Ключ) <> Тип("Неопределено") Тогда
            ПроверитьСвойКлюч(Ключ);
            Ключи.Добавить(Ключ);
        КонецЕсли;
    КонецЦикла;
    Возврат Ключи;
КонецФункции

Процедура ПроверитьСвойКлюч(Ключ)
    Если ТипЗнч(Ключ) <> Тип("Строка") Тогда
        ВызватьИсключение "Собственный ключ должен иметь тип Строка";
    КонецЕсли;
    Если СтрДлина(Ключ) < 1 Или СтрДлина(Ключ) > 20 Тогда
        ВызватьИсключение "Собственный ключ должен иметь длину от 1 до 20";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьСвоиСсылки(ОбъектПерерасчета, ВидРасчета)
    Если ТипЗнч(ОбъектПерерасчета) <> Тип("ДокументСсылка.УчебныйРегистраторПерерасчета85")
        Или ТипЗнч(ВидРасчета) <> Тип("ПланВидовРасчетаСсылка.УчебныеВидыПерерасчета85") Тогда
        ВызватьИсключение "Нужны ссылки только своего подготовленного документа и плана";
    КонецЕсли;
    Если ОбъектПерерасчета <> Документы.УчебныйРегистраторПерерасчета85.ПустаяСсылка()
        Или ВидРасчета <> ПланыВидовРасчета.УчебныеВидыПерерасчета85.ПустаяСсылка() Тогда
        ВызватьИсключение "В этом черновом опыте оба ссылочных ключа должны быть явно пустыми";
    КонецЕсли;
КонецПроцедуры

Функция ДобавитьСвоюЗапись(Набор, Ключ, ОбъектПерерасчета, ВидРасчета)
    ПроверитьСвойКлюч(Ключ);
    ПроверитьСвоиСсылки(ОбъектПерерасчета, ВидРасчета);
    Для Каждого Существующая Из Набор Цикл
        Если Существующая.Ключ85 = Ключ Тогда
            ВызватьИсключение "Наш собственный черновик не принимает повтор ключа";
        КонецЕсли;
    КонецЦикла;
    Запись = Набор.Добавить();
    Запись.ОбъектПерерасчета = ОбъектПерерасчета;
    Запись.ВидРасчета = ВидРасчета;
    Запись.Ключ85 = Ключ;
    Возврат Запись;
КонецФункции

Процедура ПроверитьСвоюЗапись(Запись, Ключ, ОбъектПерерасчета, ВидРасчета)
    ПроверитьСвоиСсылки(Запись.ОбъектПерерасчета, Запись.ВидРасчета);
    ПроверитьСвойКлюч(Запись.Ключ85);
    Если Запись.ОбъектПерерасчета <> ОбъектПерерасчета Или Запись.ВидРасчета <> ВидРасчета Или Запись.Ключ85 <> Ключ Тогда
        ВызватьИсключение "Полный состав трех полей собственной строки не совпал";
    КонецЕсли;
КонецПроцедуры

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

Процедура ПроверитьСвойИндекс(Индекс, Количество)
    Если ТипЗнч(Индекс) <> Тип("Число") Тогда
        ВызватьИсключение "Собственный индекс должен иметь тип Число";
    КонецЕсли;
    Если Индекс <> Цел(Индекс) Или Индекс < 0 Или Индекс >= Количество Тогда
        ВызватьИсключение "Собственный индекс должен быть целым от 0 до количества минус 1";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьНеверныйСвойИндекс(Индекс, Количество)
    Отклонен = Ложь;
    Попытка
        ПроверитьСвойИндекс(Индекс, Количество);
    Исключение
        Отклонен = Истина;
        Сообщить("Ручной опыт: собственный неверный индекс отклонен. " + ОписаниеОшибки());
    КонецПопытки;
    Если Не Отклонен Тогда
        ВызватьИсключение "Ожидалось отклонение собственного неверного индекса";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьНеверныйСвойКлюч(Ключ)
    Отклонен = Ложь;
    Попытка
        ПроверитьСвойКлюч(Ключ);
    Исключение
        Отклонен = Истина;
        Сообщить("Ручной опыт: собственный неверный ключ отклонен. " + ОписаниеОшибки());
    КонецПопытки;
    Если Не Отклонен Тогда
        ВызватьИсключение "Ожидалось отклонение собственного неверного ключа";
    КонецЕсли;
КонецПроцедуры
УчебныйПускПерерасчета85.Форма

Собственная новая внешняя обработка УчебныйПускПерерасчета85 → Управляемая форма Форма → Модуль

Отдельный полный модуль собственной формы запуска именно этого урока; здесь не запускался.

&НаКлиенте
Процедура Выполнить(Команда)
    ВыполнитьНаСервере();
    Сообщить("Учебный опыт завершен без записи набора в базу");
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
    УчебныйНаборПерерасчета85.ВыполнитьПример();
КонецПроцедуры

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

  1. Полная read-only проверка версии и своего минимального стенда стоит до создания набора и получения ссылок. Совпадение только имени перерасчета без его родительской схемы недостаточно.

  2. ПустаяСсылка собственного документа и плана даёт конкретные ссылочные типы. В нашем опыте это намеренно незаполненные ключи: документов и видов расчета в базе нет, готовность к записи не обещается.

  3. СоздатьНаборЗаписей native возвращает пустой набор. Проверить Количество=0 и Метаданные()=подготовленной Очередь85; никакие существующие строки не считаны.

  4. Индекс 0 в пустом наборе отклоняет собственный валидатор до Получить или []. Это не проверка неизвестного поведения платформы при выходе за границы.

  5. Добавить возвращает новую собственную запись. До вызова проверяются тип/длина своего ключа и типы пустых ссылок; повтор ключа запрещён нашим дополнительным правилом. Отдельно проверяются строковые границы 1/20 символов и четыре плохих ключа Неопределено, число, пустая строка,21 символ. Они не добавляются. Записать нигде не вызывается.

  6. В три записи явно записать все три поля: пустой документ, пустой вид расчета, ключи A,B,C. Результат85 — ресурс родительского регистра, а не поле строки перерасчета: его здесь не присваивать.

  7. Полный состав проверяется через Получить и [] для каждого индекса: обе конкретные пустые ссылки, строковый ключ и Индекс полученной записи. Native Получить работает аналогично [].

  8. Проверить собственные нижнюю/верхнюю границы 0/2 и отрицательные входы Неопределено, строка "1",-1,3,1.5. Catch охватывает только подготовительный валидатор; реальные ошибки добавления/полного чтения не поглощаются.

  9. Создать второй свой пустой набор и добавить D. Индекс(D) первого набора должен быть -1, а второго 0: ищем запись, не просто равный текст поля.

  10. Повторно проверить полные независимые составы A,B,C и D. По выходу все объекты остаются только в памяти; никакая зарегистрированная очередь не изменялась.

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

  1. Начальный набор пуст; Метаданные возвращает собственную Очередь85.

  2. Полный набор A,B,C: на индексах 0,1,2 все три поля и их типы совпадают. Повторные чтения через [] также полностью проверяются.

  3. Четыре плохих ключа и шесть конкретных неправильных индексов отклоняются собственным правилом при будущем ручном запуске. Ключи длиной 1/20 и оба реальных граничных индекса допустимы.

  4. Запись D находится только во втором наборе: -1 в первом,0 во втором. Первый набор остаётся A,B,C, второй D.

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

Полный самостоятельный модуль выполняет конкретное редактирование только собственного чернового набора в памяти и проверяет все поля результата. Это не перерасчёт записанных движений и не выполнение нами внутри 1С.

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

  1. Индекс начинается с 0. -1 означает, что переданная запись не найдена; это не индекс последней строки.

  2. Одинаковые значения полей двух отдельных записей не обещают общую принадлежность набору. В опыте передаётся реальная запись своего другого набора, не неизвестный исходный объект.

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

  4. Ни Прочитать, ни Записать, ни восстановление записанного набора не используются. СоздатьНаборЗаписей даёт новый пустой набор; все строки добавлены или загружены нашим кодом. Удаление и очистка затрагивают только этот набор в памяти.

  5. ЭтотОбъект не используется: основной код находится в серверном общем модуле, а модуль набора перерасчета пуст. Свойство отсутствующего модульного контекста не подменяется параметром.

  6. Read-only guard сверяет доступную собственную схему перед созданием набора. Пустые остальные модули, отсутствие расширений и предопределённых элементов заданы точной подготовкой; guard не обещает анализа текстов сторонних модулей или проверки произвольной установленной конфигурации.

  7. В native ИзмерениеРегистра текст описывает измерение, но строка Тип называет РегистрРасчета. Код не угадывает ТипЗнч этого метаобъекта: сравнивает его с настоящим подготовленным родительским измерением. Тип строкового поля проверяется у родителя.

  8. Python-проверки — модель полностью заданных собственных значений и статическая сверка API установленной 8.5.1.1343. Они не выполняют BSL, не создают конфигурацию и не доказывают успешный опыт в 1С.

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

Переупорядочить и удалить свои черновые записи без удаления из базы

Сдвигаем собственную B к концу и началу набора, затем удаляем A по объекту, B по текущему индексу и очищаем оставшуюся C. После каждого действия проверяются все три поля всех оставшихся записей.

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

Полный серверный общий модуль УчебноеПеремещениеПерерасчета85 собственной новой конфигурации УчебныйПерерасчет85. Все помощники предоставлены; отдельная полная форма запуска дана в подготовке/supportingModules. Запуск в 1С здесь не проверялся.

Подготовка

  1. Создайте НОВУЮ отдельную пустую учебную информационную базу на точной 8.5.1.1343 и конфигурацию УчебныйПерерасчет85. Не используйте рабочую базу или расширение готовой конфигурации. Никаких подписок, общих реквизитов, иных регистров, справочников или документов.

  2. Конфигуратор → Планы видов расчета → новый УчебныеВидыПерерасчета85. Использование периода действия=Нет; Зависимость от видов расчета=Не использовать; список базовых планов пуст. Без собственных реквизитов/табличных частей, предопределённых видов и кода модулей.

  3. Конфигуратор → Регистры расчета → новый УчебныйРегистрПерерасчета85. План видов расчета=УчебныеВидыПерерасчета85, периодичность=Месяц, Период действия=Нет, Базовый период=Нет. График не назначайте. Модули менеджера и набора записей пустые.

  4. У своего регистра единственное измерение Ключ85: единственный тип Строка, длина 20, допустимая длина Переменная. Единственный ресурс Результат85: единственный тип Число, длина 12, точность 2, допустимый знак Любой. Собственных реквизитов нет.

  5. У регистра → Перерасчеты → новый Очередь85 → Измерения → единственный Ключ85. В свойстве Измерение регистра выберите именно измерение Ключ85 родительского УчебныйРегистрПерерасчета85. Данные ведущих регистров пусты. Модуль набора записей перерасчета пуст.

  6. Конфигуратор → Документы → новый УчебныйРегистраторПерерасчета85. Проведение=Разрешить; в Движения включите только УчебныйРегистрПерерасчета85. Собственных реквизитов и табличных частей нет. Все объектные/менеджерские модули пустые; не создавайте документ и не проводите его.

  7. Остальные объектные модули, модули приложения и сеанса оставьте пустыми; не подключайте расширений, внешних обработчиков или подписок. Предопределённых элементов плана не создавайте. После ручной подготовки выполните проверку конфигурации и обновление учебной конфигурации базы. Здесь такая конфигурация и 1С не запускались.

  8. Все три поля каждой своей строки: ОбъектПерерасчета — пустая ссылка именно своего документа; ВидРасчета — пустая ссылка именно своего плана; Ключ85 — собственная строка 1..20. Пустые ссылки означают незаполненные учебные ключи, не существующие документы/виды и не готовые к записи данные.

  9. Конфигуратор → Общие → Общие модули → УчебноеПеремещениеПерерасчета85. Создайте отдельный неглобальный серверный общий модуль: Сервер=Да, Вызов сервера=Нет, Привилегированный=Нет, оба клиентских флага и внешнее соединение=Нет, повторное использование возвращаемых значений=Не использовать. Весь основной код вставьте на уровне этого модуля, не внутрь иной процедуры.

  10. Для ЭТОГО урока создайте собственную новую внешнюю обработку УчебныйПускПерерасчета85 с управляемой формой Форма, командой Выполнить и её кнопкой. Полный отдельный модуль формы ниже; не смешивайте его директивы с серверным общим модулем. Для другого урока используйте его собственный модуль формы и общее имя из соответствующей подготовки:

    &НаКлиенте
    Процедура Выполнить(Команда)
    ВыполнитьНаСервере();
    Сообщить("Учебный опыт завершен без записи набора в базу");
    КонецПроцедуры

    &НаСервереБезКонтекста
    Процедура ВыполнитьНаСервере()
    УчебноеПеремещениеПерерасчета85.ВыполнитьПример();
    КонецПроцедуры

Процедура ВыполнитьПример() Экспорт
    ПроверитьСвойСтендПерерасчета();
    ОбъектПерерасчета = Документы.УчебныйРегистраторПерерасчета85.ПустаяСсылка();
    ВидРасчета = ПланыВидовРасчета.УчебныеВидыПерерасчета85.ПустаяСсылка();
    ПроверитьСвоиСсылки(ОбъектПерерасчета, ВидРасчета);
    Набор = СоздатьСвойПустойНабор();
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи(), ОбъектПерерасчета, ВидРасчета);
    ЗаписьA = ДобавитьСвоюЗапись(Набор, "A", ОбъектПерерасчета, ВидРасчета);
    ЗаписьB = ДобавитьСвоюЗапись(Набор, "B", ОбъектПерерасчета, ВидРасчета);
    ДобавитьСвоюЗапись(Набор, "C", ОбъектПерерасчета, ВидРасчета);
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи("A", "B", "C"), ОбъектПерерасчета, ВидРасчета);
    ПроверитьНеверноеСвоёСмещение(1, Неопределено, 3);
    ПроверитьНеверноеСвоёСмещение(1, "1", 3);
    ПроверитьНеверноеСвоёСмещение(1, 1.5, 3);
    ПроверитьНеверноеСвоёСмещение(1, -2, 3);
    ПроверитьНеверноеСвоёСмещение(1, 2, 3);
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи("A", "B", "C"), ОбъектПерерасчета, ВидРасчета);
    ПроверитьСвоёСмещение(Набор.Индекс(ЗаписьB), 1, Набор.Количество());
    Набор.Сдвинуть(ЗаписьB, 1);
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи("A", "C", "B"), ОбъектПерерасчета, ВидРасчета);
    ПроверитьСвоёСмещение(Набор.Индекс(ЗаписьB), -2, Набор.Количество());
    Набор.Сдвинуть(ЗаписьB, -2);
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи("B", "A", "C"), ОбъектПерерасчета, ВидРасчета);
    Набор.Удалить(ЗаписьA);
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи("B", "C"), ОбъектПерерасчета, ВидРасчета);
    ПроверитьСвойИндекс(0, Набор.Количество());
    Набор.Удалить(0);
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи("C"), ОбъектПерерасчета, ВидРасчета);
    ПроверитьНеверныйСвойИндекс(1, Набор.Количество());
    Набор.Очистить();
    ПроверитьСвойПолныйПорядок(Набор, СвоиКлючи(), ОбъектПерерасчета, ВидРасчета);
    ПроверитьНеверныйСвойИндекс(0, Набор.Количество());
КонецПроцедуры

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

Функция СоздатьСвойПустойНабор()
    Набор = РегистрыРасчета.УчебныйРегистрПерерасчета85.Перерасчеты.Очередь85.СоздатьНаборЗаписей();
    МетаПерерасчет = Метаданные.РегистрыРасчета.УчебныйРегистрПерерасчета85.Перерасчеты.Очередь85;
    Если Набор.Количество() <> 0 Или Набор.Метаданные() <> МетаПерерасчет Тогда
        ВызватьИсключение "Создан не пустой набор своего перерасчета Очередь85";
    КонецЕсли;
    Возврат Набор;
КонецФункции

Функция СвоиКлючи(Первый = Неопределено, Второй = Неопределено, Третий = Неопределено)
    Ключи = Новый Массив;
    Кандидаты = Новый Массив;
    Кандидаты.Добавить(Первый);
    Кандидаты.Добавить(Второй);
    Кандидаты.Добавить(Третий);
    Для Каждого Ключ Из Кандидаты Цикл
        Если ТипЗнч(Ключ) <> Тип("Неопределено") Тогда
            ПроверитьСвойКлюч(Ключ);
            Ключи.Добавить(Ключ);
        КонецЕсли;
    КонецЦикла;
    Возврат Ключи;
КонецФункции

Процедура ПроверитьСвойКлюч(Ключ)
    Если ТипЗнч(Ключ) <> Тип("Строка") Тогда
        ВызватьИсключение "Собственный ключ должен иметь тип Строка";
    КонецЕсли;
    Если СтрДлина(Ключ) < 1 Или СтрДлина(Ключ) > 20 Тогда
        ВызватьИсключение "Собственный ключ должен иметь длину от 1 до 20";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьСвоиСсылки(ОбъектПерерасчета, ВидРасчета)
    Если ТипЗнч(ОбъектПерерасчета) <> Тип("ДокументСсылка.УчебныйРегистраторПерерасчета85")
        Или ТипЗнч(ВидРасчета) <> Тип("ПланВидовРасчетаСсылка.УчебныеВидыПерерасчета85") Тогда
        ВызватьИсключение "Нужны ссылки только своего подготовленного документа и плана";
    КонецЕсли;
    Если ОбъектПерерасчета <> Документы.УчебныйРегистраторПерерасчета85.ПустаяСсылка()
        Или ВидРасчета <> ПланыВидовРасчета.УчебныеВидыПерерасчета85.ПустаяСсылка() Тогда
        ВызватьИсключение "В этом черновом опыте оба ссылочных ключа должны быть явно пустыми";
    КонецЕсли;
КонецПроцедуры

Функция ДобавитьСвоюЗапись(Набор, Ключ, ОбъектПерерасчета, ВидРасчета)
    ПроверитьСвойКлюч(Ключ);
    ПроверитьСвоиСсылки(ОбъектПерерасчета, ВидРасчета);
    Для Каждого Существующая Из Набор Цикл
        Если Существующая.Ключ85 = Ключ Тогда
            ВызватьИсключение "Наш собственный черновик не принимает повтор ключа";
        КонецЕсли;
    КонецЦикла;
    Запись = Набор.Добавить();
    Запись.ОбъектПерерасчета = ОбъектПерерасчета;
    Запись.ВидРасчета = ВидРасчета;
    Запись.Ключ85 = Ключ;
    Возврат Запись;
КонецФункции

Процедура ПроверитьСвоюЗапись(Запись, Ключ, ОбъектПерерасчета, ВидРасчета)
    ПроверитьСвоиСсылки(Запись.ОбъектПерерасчета, Запись.ВидРасчета);
    ПроверитьСвойКлюч(Запись.Ключ85);
    Если Запись.ОбъектПерерасчета <> ОбъектПерерасчета Или Запись.ВидРасчета <> ВидРасчета Или Запись.Ключ85 <> Ключ Тогда
        ВызватьИсключение "Полный состав трех полей собственной строки не совпал";
    КонецЕсли;
КонецПроцедуры

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

Процедура ПроверитьСвойИндекс(Индекс, Количество)
    Если ТипЗнч(Индекс) <> Тип("Число") Тогда
        ВызватьИсключение "Собственный индекс должен иметь тип Число";
    КонецЕсли;
    Если Индекс <> Цел(Индекс) Или Индекс < 0 Или Индекс >= Количество Тогда
        ВызватьИсключение "Собственный индекс должен быть целым от 0 до количества минус 1";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьНеверныйСвойИндекс(Индекс, Количество)
    Отклонен = Ложь;
    Попытка
        ПроверитьСвойИндекс(Индекс, Количество);
    Исключение
        Отклонен = Истина;
        Сообщить("Ручной опыт: собственный неверный индекс отклонен. " + ОписаниеОшибки());
    КонецПопытки;
    Если Не Отклонен Тогда
        ВызватьИсключение "Ожидалось отклонение собственного неверного индекса";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьСвоёСмещение(Индекс, Смещение, Количество)
    ПроверитьСвойИндекс(Индекс, Количество);
    Если ТипЗнч(Смещение) <> Тип("Число") Тогда
        ВызватьИсключение "Собственное смещение должно иметь тип Число";
    КонецЕсли;
    Если Смещение <> Цел(Смещение) Тогда
        ВызватьИсключение "Собственное смещение должно быть целым";
    КонецЕсли;
    ПроверитьСвойИндекс(Индекс + Смещение, Количество);
КонецПроцедуры

Процедура ПроверитьНеверноеСвоёСмещение(Индекс, Смещение, Количество)
    Отклонено = Ложь;
    Попытка
        ПроверитьСвоёСмещение(Индекс, Смещение, Количество);
    Исключение
        Отклонено = Истина;
        Сообщить("Ручной опыт: собственное неверное смещение отклонено. " + ОписаниеОшибки());
    КонецПопытки;
    Если Не Отклонено Тогда
        ВызватьИсключение "Ожидалось отклонение собственного неверного смещения";
    КонецЕсли;
КонецПроцедуры
УчебныйПускПерерасчета85.Форма

Собственная новая внешняя обработка УчебныйПускПерерасчета85 → Управляемая форма Форма → Модуль

Отдельный полный модуль собственной формы запуска именно этого урока; здесь не запускался.

&НаКлиенте
Процедура Выполнить(Команда)
    ВыполнитьНаСервере();
    Сообщить("Учебный опыт завершен без записи набора в базу");
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
    УчебноеПеремещениеПерерасчета85.ВыполнитьПример();
КонецПроцедуры

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

  1. Сначала подготовить и проверить тот же новый собственный стенд. Набор создаётся пустым; три строки A,B,C принадлежат этому текущему набору, их ссылки намеренно пусты.

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

  3. Пять плохих смещений от индекса 1 — Неопределено,"1",1.5,-2,+2 — отклоняет только собственный валидатор, без вызова Сдвинуть. Полный A,B,C после них должен сохраниться.

  4. Native положительное смещение увеличивает индекс. Сдвинуть(ЗаписьB,1) перемещает B с 1 на 2: полный новый порядок A,C,B.

  5. Native отрицательное смещение направлено к началу. Теперь B имеет индекс 2; Сдвинуть(B,-2) даёт полный порядок B,A,C.

  6. Удалить принимает объект записи либо числовой индекс. Удалить(ЗаписьA) удаляет именно свою A, независимо от её перемещения на индекс 1. Полный остаток B,C.

  7. Перед удалением по индексу проверить текущие границы. Удалить(0) удаляет B уже из B,C, остаток C, а не исходную A.

  8. При одной строке собственное правило отклоняет индекс 1. Очистить удаляет все записи только из набора в памяти, полный остаток пуст.

  9. Индекс 0 после очистки снова недопустим по нашему правилу. Удалённые объекты строк не читаются, их потенциальная инвалидированность не угадывается.

  10. Все промежуточные проверки читают Получить и [] и сравнивают три поля, типы и Индекс. Набор ни разу не считан и не записан.

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

  1. Полная последовательность составов: A,B,C → A,C,B → B,A,C → B,C → C → пусто.

  2. В каждом непустом составе ОбъектПерерасчета и ВидРасчета — свои конкретные пустые ссылки, Ключ85 — ожидаемая строка; индекс каждой записи совпадает.

  3. Пять неверных смещений, индекс 1 при одной строке и индекс 0 после очистки отклоняются собственной проверкой до операции.

  4. Ни один catch не охватывает Сдвинуть, Удалить или Очистить. Неожиданная ошибка реальной операции прерывает урок.

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

Полный самостоятельный модуль выполняет конкретное редактирование только собственного чернового набора в памяти и проверяет все поля результата. Это не перерасчёт записанных движений и не выполнение нами внутри 1С.

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

  1. Удалить и Очистить здесь удаляют только собственные записи памяти. Записать с замещением — другое действие с базой; такого действия в коде нет.

  2. Смещение — количество позиций, не абсолютный целевой индекс. Перед вторым смещением B уже находится на 2, поэтому используется -2.

  3. После удаления индексы оставшихся записей изменяются. Проверяется текущий состав, а не сохранённый прежний индекс.

  4. Поведение native при дробном смещении, чужой или удалённой записи и выходе за пределы здесь не обещается: такие вызовы не выполняются.

  5. Ни Прочитать, ни Записать, ни восстановление записанного набора не используются. СоздатьНаборЗаписей даёт новый пустой набор; все строки добавлены или загружены нашим кодом. Удаление и очистка затрагивают только этот набор в памяти.

  6. ЭтотОбъект не используется: основной код находится в серверном общем модуле, а модуль набора перерасчета пуст. Свойство отсутствующего модульного контекста не подменяется параметром.

  7. Read-only guard сверяет доступную собственную схему перед созданием набора. Пустые остальные модули, отсутствие расширений и предопределённых элементов заданы точной подготовкой; guard не обещает анализа текстов сторонних модулей или проверки произвольной установленной конфигурации.

  8. В native ИзмерениеРегистра текст описывает измерение, но строка Тип называет РегистрРасчета. Код не угадывает ТипЗнч этого метаобъекта: сравнивает его с настоящим подготовленным родительским измерением. Тип строкового поля проверяется у родителя.

  9. Python-проверки — модель полностью заданных собственных значений и статическая сверка API установленной 8.5.1.1343. Они не выполняют BSL, не создают конфигурацию и не доказывают успешный опыт в 1С.

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

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

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

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

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