В практике работы с платформой 1С:Предприятие 7.7 нередко случаются ситуации, когда штатные обработки выполняются с некорректными параметрами. Типичный пример — запуск обработки «Формирование цен» с установкой цен «по себестоимости». Если по части товаров на складе отсутствуют остатки, их себестоимость в системе принимается равной нулю, и розничные цены затираются нулевыми значениями. Поскольку цены в 1С 7.7 являются периодическими реквизитами, ручное исправление каждой карточки товара занимает огромное количество времени. В этой статье мы разберем, как автоматизировать процесс отката цен и очистить историю от ошибочных записей.
Прежде чем приступать к исправлению, проанализируем причину проблемы. В типовых конфигурациях (например, «Торговля и Склад») механизм получения себестоимости обращается к регистрам остатков. Если товара нет в наличии, функция возвращает 0. Обработка записывает этот ноль в периодический реквизит справочника Цены на текущую дату. Чтобы вернуть состояние цен к моменту «до обработки», нам необходимо найти в истории периодических реквизитов все записи, сделанные конкретной датой, и удалить их.
Любые манипуляции с историей значений и прямым удалением записей из базы данных несут риски. Обязательно сделайте резервную копию базы данных (файл 1Cv7.77 или SQL-бэкап) перед запуском любых корректирующих обработок.
Основным инструментом для работы с историей изменений в 1С 7.7 является объект Периодический. Разберем по шагам алгоритм, который позволит нам найти и удалить записи на определенную дату. Основная сложность здесь заключается в том, что записи могут быть установлены как «вручную» (через карточку или программно), так и «документами».
Рассмотрим пример кода для обработки, которая обходит справочник номенклатуры и чистит историю цен:
Процедура ВыполнитьОткатЦен()
СпрНоменклатура = СоздатьОбъект("Справочник.Номенклатура");
СпрЦены = СоздатьОбъект("Справочник.Цены");
ОбъектПериод = СоздатьОбъект("Периодический");
ДатаОшибки = '22.08.2017'; // Укажите дату, когда была запущена обработка
СпрНоменклатура.ВыбратьЭлементы();
Пока СпрНоменклатура.ПолучитьЭлемент() = 1 Цикл
// Пропускаем группы, работаем только с элементами
Если СпрНоменклатура.ЭтоГруппа() = 1 Тогда
Продолжить;
КонецЕсли;
// Переходим к подчиненному справочнику цен
СпрЦены.ИспользоватьВладельца(СпрНоменклатура.ТекущийЭлемент());
СпрЦены.ВыбратьЭлементы();
Пока СпрЦены.ПолучитьЭлемент() = 1 Цикл
// Настраиваем объект для работы с конкретным реквизитом "Цена"
// В типовых конфигурациях 7.7 идентификатор реквизита обычно "Цена"
ОбъектПериод.ИспользоватьОбъект("Цена", СпрЦены.ТекущийЭлемент());
// Пытаемся найти значение именно на нашу дату
Если ОбъектПериод.НайтиЗначение(ДатаОшибки) = 1 Тогда
// Проверяем, совпадает ли дата найденного значения
Если ОбъектПериод.ДатаЗнач = ДатаОшибки Тогда
// Важный момент: проверка, не установлена ли цена документом
Если ОбъектПериод.ТекущийДокумент().Выбран() = 0 Тогда
Попытка
ОбъектПериод.Удалить();
Сообщить("Удалена цена для: " + СпрНоменклатура.Наименование);
Исключение
Сообщить("Ошибка удаления: " + ОписаниеОшибки());
КонецПопытки;
Иначе
Сообщить("Цена установлена документом " + ОбъектПериод.ТекущийДокумент() + ". Пропуск.");
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Проанализируем используемые методы, чтобы понять, как работает очистка:
ИспользоватьОбъект(ИмяРеквизита, Ссылка) — связывает объект Периодический с конкретным полем справочника. Важно помнить, что в 1С 7.7 цены часто хранятся в подчиненном справочнике Цены, поэтому сначала нужно выбрать элемент этого справочника.НайтиЗначение(Дата, Режим) — позволяет быстро позиционироваться на нужной дате в истории. Использование этого метода гораздо эффективнее, чем полный перебор истории через ВыбратьЗначения().ТекущийДокумент() — это критически важная проверка. Если метод Выбран() возвращает 1, это означает, что запись в истории порождена проведением документа (например, «Установка цен»). Платформа 7.7 запрещает удаление таких записей методом Удалить() — это вызовет фатальную ошибку.Если вы выяснили, что цены были установлены не просто обработкой «вручную», а путем автоматического формирования документа «Установка цен ТМЦ», то метод Удалить() не сработает. В этом случае у вас есть два пути:
СделатьНепроведенным().Иногда вместо удаления записей проще создать новую «правильную» запись той же датой. Если вы знаете, что до запуска обработки цены были корректными, можно написать скрипт, который:
ДатаОшибки - 1).ДатаОшибки.Это не удалит историю, но «перекроет» нулевые значения актуальными данными. Для этого используется метод Значение объекта Периодический и метод Записать().
При работе с большими справочниками (десятки тысяч позиций) работа через объект Периодический может быть медленной. Чтобы ускорить процесс, мы рекомендуем обернуть цикл обработки в транзакцию:
НачатьТранзакцию();
// ... ваш код цикла ...
ЗафиксироватьТранзакцию();
Это позволит платформе 1С 7.7 выполнить все операции с файлом 1SCONST.DBF (где хранится история периодических реквизитов) за один проход, что сократит время выполнения с часов до нескольких минут.
Помните, что после программного удаления или изменения цен рекомендуется обновить индексы и проверить актуальность отчетов, использующих цены для расчета себестоимости или ожидаемой выручки.