Как сформировать Отчет о розничных продажах в 1С:УТ 10.3, если кассовая смена была закрыта позже дня продаж?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

Мы сталкиваемся с распространенной ситуацией, когда по различным причинам, таким как отключение электроэнергии, кассовая смена не была закрыта вовремя, и Z-отчет был сформирован на следующий день. В результате этого 1С:Управление торговлей 10.3 (УТ 10.3) не сформировала необходимый "Отчет о розничных продажах" за предыдущий день. Возникает вопрос: как нам сформировать этот отчет, чтобы корректно отразить выручку и движения товаров?

Для начала, давайте разберем, как обычно работает механизм формирования "Отчета о розничных продажах" в 1С:УТ 10.3. Документ "Отчет о розничных продажах" является центральным для учета розничной выручки и формируется, как правило, автоматически при закрытии кассовой смены. В этот момент система обрабатывает все "Чеки ККМ", зарегистрированные в течение смены, агрегирует их данные и создает единый документ "Отчет о розничных продажах". После успешного создания отчета, "Чеки ККМ" могут получать статус "Архивный" или "Свернут" и их движения "переносятся" в сформированный отчет. При этом данные о продажах регистрируются в регистре накопления "Товары в рознице", и именно по этому регистру мы можем определить, были ли чеки уже свернуты или все еще "висят" несвернутыми.

Наша задача заключается в том, чтобы найти несвернутые "Чеки ККМ" за нужную дату и на их основании сформировать "Отчет о розничных продажах". Рассмотрим несколько подходов к решению этой проблемы.

Подход 1: Повторное закрытие смены с указанием предыдущей даты (стандартный метод)

Одним из предложенных на форуме вариантов является попытка повторного запуска процедуры закрытия кассовой смены. Хотя интуитивно кажется, что если Z-отчет уже снят, то смена закрыта и повторное закрытие невозможно, в контексте 1С это может иметь свои нюансы. Физический Z-отчет на кассовом аппарате действительно снимается один раз, но внутренняя обработка "Чеков ККМ" в 1С может быть отдельным процессом.

  1. Проверяем состояние кассовой смены: Прежде всего, нам необходимо убедиться, что на физическом фискальном регистраторе (ККМ) смена не открыта. Если Z-отчет был снят, то с точки зрения кассового аппарата смена действительно закрыта.
  2. Переходим к закрытию кассовой смены в 1С: Откроем 1С:УТ 10.3 и перейдем в меню Сервис / Торговое оборудование / Работа с ККМ / Закрытие кассовой смены.
  3. Выбираем кассу и указываем дату: В открывшейся форме нам потребуется выбрать нужную кассу ККМ. Критически важно здесь попробовать вручную указать дату, за которую должен быть сформирован отчет. Это должна быть именно та дата, когда фактически были совершены продажи (предыдущий день), а не дата фактического закрытия Z-отчета.
  4. Запускаем процесс: Попробуем запустить процедуру закрытия смены. Если "Чеки ККМ" за указанную дату остались не связанными с каким-либо "Отчетом о розничных продажах", система может обработать их и сформировать соответствующий документ. Система будет искать "Чеки ККМ", которые не имеют ссылки на документ "Отчет о розничных продажах" в соответствующем реквизите.
  5. Проверяем результат: После попытки закрытия, мы должны проверить, был ли сформирован "Отчет о розничных продажах" за нужную дату. Для этого можем посмотреть список документов "Отчеты о розничных продажах" или проанализировать движения по регистру Товары в рознице. Если чеки были успешно свернуты, движения по регистру должны быть соответствующим образом учтены в новом отчете.

Важно понимать, почему этот метод может сработать, несмотря на снятый Z-отчет. Часто закрытие кассовой смены в 1С состоит из двух частей: команды фискальному регистратору на снятие Z-отчета и внутренней обработки данных по "Чекам ККМ". Если первая часть (снятие Z-отчета) произошла, а вторая (формирование отчета в 1С) не завершилась по какой-либо причине (например, обрыв связи или ошибка), то "Чеки ККМ" могут остаться "несвернутыми". Повторный запуск закрытия с правильной датой дает шанс системе завершить именно вторую часть процесса.

Подход 2: Создание внешней обработки или модификация стандартного механизма (программистский метод)

Если стандартный подход с повторным закрытием смены не сработал, или если мы хотим иметь более точечный контроль над процессом, самым надежным решением будет создание собственной внешней обработки. Этот подход является более трудоемким, но предоставляет максимальную гибкость и контроль.

  1. Анализ существующей логики: Прежде всего, нам необходимо понять, как 1С:УТ 10.3 сворачивает "Чеки ККМ" в "Отчет о розничных продажах" при стандартном закрытии смены. Обычно эта логика находится в модуле объекта документа ЗакрытиеКассовойСмены или в каком-либо общем модуле, который вызывается при его проведении. Мы выясним, какие регистры затрагиваются (прежде всего ТоварыВРознице, а также ВыручкаККМ, Продажи), и как происходит выборка "несвернутых" чеков.
  2. Создание новой внешней обработки: Разработаем новую внешнюю обработку. Она должна будет иметь как минимум следующие элементы управления:
    • Поле выбора КассаККМ, чтобы указать, по какой кассе необходимо сформировать отчет.
    • Поле ввода ДатаОтчета, для указания даты, за которую формируется "Отчет о розничных продажах".
    • Кнопка "Сформировать отчет".
  3. Выборка несвернутых "Чеков ККМ": В коде обработки мы сформируем запрос к базе данных, который выберет все "Чеки ККМ" за указанную дату и выбранную кассу, которые еще не были связаны с "Отчетом о розничных продажах". Признаком несвернутого чека является отсутствие значения в реквизите ОтчетОРозничныхПродажах у документа ЧекККМ и наличие движений по регистру ТоварыВРознице.

Рассмотрим пример запроса для получения несвернутых чеков:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ЧекККМ.Ссылка КАК Ссылка,
    |    ЧекККМ.Номер КАК Номер,
    |    ЧекККМ.Дата КАК Дата,
    |    ЧекККМ.КассаККМ КАК КассаККМ,
    |    ЧекККМ.Склад КАК Склад,
    |    ЧекККМ.Организация КАК Организация,
    |    ЧекККМ.СуммаДокумента КАК СуммаДокумента,
    |    ЧекККМ.ВидОплаты КАК ВидОплаты,
    |    ЧекККМ.ВалютаДокумента КАК ВалютаДокумента
    |ИЗ
    |    Документ.ЧекККМ КАК ЧекККМ
    |ГДЕ
    |    ЧекККМ.Дата МЕЖДУ &НачалоДня И &КонецДня
    |    И ЧекККМ.КассаККМ = &КассаККМ
    |    И ЧекККМ.ОтчетОРозничныхПродажах ЕСТЬ NULL
    |    И ЧекККМ.Проведен";

Запрос.УстановитьПараметр("НачалоДня", НачалоДня(ДатаОтчета));
Запрос.УстановитьПараметр("КонецДня", КонецДня(ДатаОтчета));
Запрос.УстановитьПараметр("КассаККМ", КассаККМ);

РезультатЗапроса = Запрос.Выполнить().Выгрузить();
  1. Создание и заполнение "Отчета о розничных продажах": После того как мы получили список несвернутых чеков, мы создадим новый документ ОтчетОРозничныхПродажах и заполним его данными. Нам потребуется агрегировать информацию из всех найденных чеков: суммы, товары, виды оплат и т.д.

Примерный код для создания и заполнения отчета:


Если РезультатЗапроса.Количество() > 0 Тогда
    НовыйОтчет = Документы.ОтчетОРозничныхПродажах.СоздатьДокумент();
    НовыйОтчет.Дата = ДатаОтчета;
    НовыйОтчет.КассаККМ = КассаККМ;
    НовыйОтчет.Организация = РезультатЗапроса[0].Организация; // Возьмем из первого чека
    НовыйОтчет.Склад = РезультатЗапроса[0].Склад; // Возьмем из первого чека
    НовыйОтчет.ВалютаДокумента = РезультатЗапроса[0].ВалютаДокумента;

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

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

    Попытка
        НовыйОтчет.Записать(РежимЗаписиДокумента.Проведение);
        Сообщить("Отчет о розничных продажах №" + НовыйОтчет.Номер + " от " + НовыйОтчет.Дата + " успешно сформирован и проведен.");
    Исключение
        Сообщить("Ошибка при проведении Отчета о розничных продажах: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;

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

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

Дополнительные рекомендации и проверка

Независимо от выбранного подхода, всегда проводите тщательную проверку результатов:

  1. Анализ регистра "Товары в рознице": Обязательно проверяем движения по регистру Товары в рознице до и после выполнения наших действий. Мы должны убедиться, что "Чеки ККМ", которые ранее имели движения, теперь корректно "закрыты" документом "Отчет о розничных продажах".
  2. Журнал регистрации: Внимательно изучаем Журнал регистрации в 1С на предмет любых ошибок, связанных с проведением документов или инициализацией модулей. Это поможет нам выявить скрытые проблемы.
  3. Контроль остатков: Проверяем остатки товаров на складе, который используется для розничных продаж. Убеждаемся, что количество товаров уменьшилось на проданное количество, и что остатки соответствуют ожидаемым. Также проверяем остатки по организации и складам по тому типу учета, который указан в тексте ошибки (управленческий, бухгалтерский, налоговый).
  4. Ручное заполнение (если отчет создан пустым): В некоторых случаях, при сбое, система может создать пустой "Отчет о розничных продажах" без табличных частей. Если это произошло, мы можем открыть такой документ и попробовать использовать кнопку "Перезаполнить отчет о розничных продажах", если она доступна, или вручную заполнить его на основании несвернутых чеков.

Выбирая любой из этих методов, мы сможем восстановить целостность данных в нашей 1С:УТ 10.3 и корректно учесть розничные продажи, даже если кассовая смена была закрыта с задержкой.

← На главную