Как в 1С 7.7 Торговля и Склад создать отчет по последним ценам на основе документов поступления и переоценки

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

В практике работы с конфигурацией «Торговля и Склад» (ТиС) 7.7 часто возникают задачи, требующие нестандартного подхода к получению данных. Одной из таких задач является построение отчета по ценам (закупочным и розничным), где источником данных должны выступать не регистры цен или партий, а непосредственно табличные части документов: ПоступлениеТМЦ (с видом операции «Поступление в розницу») и ПереоценкаРозница. Рассмотрим, как реализовать такой алгоритм, какие технические сложности могут возникнуть и как их обойти.

Постановка задачи и анализ требований

Нам необходимо сформировать отчет, состоящий из трех колонок: Номенклатура, Цена закупочная и Цена розничная. Основная сложность заключается в фильтрации: данные должны браться только из самых последних проведенных документов указанных типов по выбранным товарам или группам товаров. Разберем, почему стандартные методы получения цен через периодические реквизиты справочника или регистры здесь не подходят: заказчику требуется видеть цену именно из первичного документа, который зафиксировал факт поступления или изменения оценки в розничной точке.

Проблема отсутствия данных в документах

Проанализируем структуру документов в типовой ТиС 7.7. Документ ПоступлениеТМЦ содержит и закупочную цену (реквизит Цена), и розничную цену (реквизит Розн_Цена). Однако документ ПереоценкаРозница предназначен для изменения розничной стоимости остатков. В его табличной части обычно присутствуют реквизиты СтараяЦена и Цена (новая розничная), но закупочная цена там отсутствует. Таким образом, при разработке алгоритма мы должны предусмотреть логику: если последний документ для товара — «Переоценка», то розничную цену берем из него, а закупочную продолжаем искать в более ранних документах поступления.

Алгоритм реализации поиска через обратный порядок

Для решения задачи «поиска последнего документа» наиболее эффективным методом в 1С 7.7 является использование объекта Документ с применением метода ОбратныйПорядок(1). Это позволяет нам не просматривать всю базу с начала времен, а двигаться от текущей даты вглубь истории. Как только мы находим нужные цены для товара, мы прекращаем поиск по этой позиции.

Рассмотрим пошагово, как реализовать этот процесс в коде:

  1. Подготовка фильтра номенклатуры. Если пользователь выбрал группы товаров, нам необходимо получить плоский список всех элементов, входящих в эти группы. Для этого удобно использовать объект СписокЗначений.
  2. Создание таблицы результатов. Создадим ТаблицаЗначений, куда будем записывать найденные данные. В ней будут колонки: Товар, ЗакупочнаяЦена, РозничнаяЦена, НайденаЗакупочная (флаг), НайденаРозничная (флаг).
  3. Перебор документов. Запускаем цикл по журналам документов в обратном хронологическом порядке.

Пример реализации инициализации фильтра и подготовки таблицы:


// Создаем список товаров для поиска
СписокТоваров = СоздатьОбъект("СписокЗначений");
// Предположим, ВыбТовар - это группа или список на форме
Если ВыбТовар.Выбран() = 1 Тогда
    Если ВыбТовар.ЭтоГруппа() = 1 Тогда
        // Рекурсивно собираем товары в список
        СпрН = СоздатьОбъект("Справочник.Номенклатура");
        СпрН.ИспользоватьРодителя(ВыбТовар);
        СпрН.ВыбратьЭлементы();
        Пока СпрН.ПолучитьЭлемент() = 1 Цикл
            Если СпрН.ЭтоГруппа() = 0 Тогда
                СписокТоваров.ДобавитьЗначение(СпрН.ТекущийЭлемент());
            КонецЕсли;
        КонецЦикла;
    Иначе
        СписокТоваров.ДобавитьЗначение(ВыбТовар);
    КонецЕсли;
КонецЕсли;

// Подготовим таблицу для хранения финальных цен
ТЗ_Результат = СоздатьОбъект("ТаблицаЗначений");
ТЗ_Результат.НоваяКолонка("Товар");
ТЗ_Результат.НоваяКолонка("ЗакупЦена", "Число");
ТЗ_Результат.НоваяКолонка("РознЦена", "Число");
ТЗ_Результат.НоваяКолонка("НайденаЗакуп", "Число");
ТЗ_Результат.НоваяКолонка("НайденаРозн", "Число");

// Заполним таблицу всеми искомыми товарами
Для и = 1 По СписокТоваров.РазмерСписка() Цикл
    ТЗ_Результат.НоваяСтрока();
    ТЗ_Результат.Товар = СписокТоваров.ПолучитьЗначение(и);
    ТЗ_Результат.НайденаЗакуп = 0;
    ТЗ_Результат.НайденаРозн = 0;
КонецЦикла;

Реализация поиска цен в документах

Теперь выясним, как правильно «прошерстить» журнал документов. Мы будем использовать объект ЖурналДокументов или прямой перебор документов определенных видов. Важно помнить, что поиск должен ограничиваться моментом, когда для всех товаров из списка найдены обе цены.


Док = СоздатьОбъект("Документ");
// Выбираем период, за который разумно искать документы (например, последние полгода)
Док.ВыбратьДокументы(ДатаКонца, ДатаНачала); 
Док.ОбратныйПорядок(1);

Пока Док.ПолучитьДокумент() = 1 Цикл
    // Проверяем тип документа
    ВидДок = Док.Вид();
    Если (ВидДок <> "ПоступлениеТМЦ") И (ВидДок <> "ПереоценкаРозница") Тогда
        Продолжить;
    КонецЕсли;

    // Документ должен быть проведен
    Если Док.Проведен() = 0 Тогда
        Продолжить;
    КонецЕсли;

    // В "ПоступлениеТМЦ" проверяем операцию - нам нужно поступление в розницу
    Если ВидДок = "ПоступлениеТМЦ" Тогда
        Если Док.ВариантПоступления <> Перечисление.ВариантыПоступления.ВРозницу Тогда
            Продолжить;
        КонецЕсли;
    КонецЕсли;

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

            // Если закупочная цена еще не найдена (берем только из Поступления)
            Если ТЗ_Результат.НайденаЗакуп = 0 Тогда
                Если ВидДок = "ПоступлениеТМЦ" Тогда
                    ТЗ_Результат.ЗакупЦена = Док.Цена;
                    ТЗ_Результат.НайденаЗакуп = 1;
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;

    // Проверка: нашли ли мы всё?
    ВсеНайдено = 1;
    ТЗ_Результат.ВыбратьСтроки();
    Пока ТЗ_Результат.ПолучитьСтроку() = 1 Цикл
        Если (ТЗ_Результат.НайденаЗакуп = 0) Или (ТЗ_Результат.НайденаРозн = 0) Тогда
            ВсеНайдено = 0; Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если ВсеНайдено = 1 Тогда Прервать; КонецЕсли;
КонецЦикла;

Оптимизация и производительность

Рассмотрим ситуацию, когда база данных содержит сотни тысяч документов. Прямой перебор строк каждого документа — операция крайне ресурсозатратная. Выясним причину: 1С 7.7 при вызове ПолучитьСтроку() обращается к файлу DT* (для DBF-версии) или выполняет SQL-запрос к таблице строк документов. Чтобы ускорить процесс, проанализируем следующие рекомендации:

Особенности партионного учета

Разберем важный момент, упомянутый в обсуждении: в ТиС 7.7 нет понятия «чистой закупочной цены» в отрыве от партий. Если товар пришел двумя партиями по разным ценам в один день, отчет зафиксирует цену из самого последнего по времени проведения документа. Это соответствует логике «крайней цены», которую обычно и хотят видеть пользователи. Если же требуется усредненная цена, то данный алгоритм (через документы) не подойдет — в этом случае необходимо обращаться к регистру ПартииНаличие.

Вывод и формирование печатной формы

После завершения цикла перебора у нас есть заполненная ТаблицаЗначений. Нам остается только вывести её в таблицу (печать). Не забудьте обработать случаи, когда цена так и не была найдена (например, товар заведен, но движений по нему не было) — в таких строках отчета можно выводить «Цена не определена».

Подытожим: реализация отчета по документам в 1С 7.7 требует четкого понимания структуры метаданных и умения работать с выборками в обратном порядке. Использование метода НайтиЗначение в ТаблицеЗначений позволяет быстро сопоставлять данные из документов со списком искомых товаров, делая инструмент удобным и точным для оперативного контроля цен.

← На главную