Как настроить периодическую выгрузку новых документов Чек ККМ из 1С в XML

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

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

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

Вариант 1. Использование механизма планов обмена (рекомендуемый способ)

Механизм планов обмена — это штатный и наиболее надежный инструмент платформы «1С:Предприятие» для фиксации изменений данных. Он обеспечивает транзакционную безопасность: если документ проводится прямо в момент выгрузки, он гарантированно попадет в следующую итерацию без риска потери данных.

Рассмотрим порядок реализации через план обмена:

  1. Создание плана обмена: В дереве метаданных конфигурации создаем новый объект ПланОбмена (например, ОбменСВнешнейСистемой). В составе плана обмена указываем документ ЧекККМ с авторегистрацией Разрешить.
  2. Создание узла: В режиме «1С:Предприятие» создаем узел обмена, для которого будет накапливаться очередь измененных документов.
  3. Чтение изменений и выгрузка: В обработке или процедуре общего модуля выбираем зарегистрированные изменения с помощью ПланыОбмена.ВыбратьИзменения(), формируем XML и удаляем регистрацию только после успешного сохранения файла.

Посмотрим на пример кода выборки изменений и сериализации в XML:


Процедура ВыгрузитьНовыеЧекиВXML(УзелОбмена, ПутьКФайлу) Экспорт

    Выборка = ПланыОбмена.ВыбратьИзменения(УзелОбмена, УзелОбмена.НомерОтправленного + 1);
    
    // Если изменений нет, прерываем выполнение
    Если Выборка.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;

    ВременныйФайл = ПутьКФайлу + ".tmp";
    
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.ОткрытьФайл(ВременныйФайл, "UTF-8");
    ЗаписьXML.ЗаписатьНачалоЭлемента("ЧекиККМ");

    Пока Выборка.Следующий() Цикл
        ДанныеОбъекта = Выборка.Получить();
        
        Если ТипЗнч(ДанныеОбъекта) = Тип("ДокументСсылка.ЧекККМ") Тогда
            ОбъектДокумент = ДанныеОбъекта.ПолучитьОбъект();
            Если ОбъектДокумент <> Неопределено Тогда
                // Сериализация стандартными средствами платформы
                СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ОбъектДокумент);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;

    ЗаписьXML.ЗаписатьКонецЭлемента();
    ЗаписьXML.Закрыть();

    // Удаляем регистрацию изменений только после успешной записи файла
    ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, УзелОбмена.НомерОтправленного + 1);

    // Атомарное перемещение во избежание чтения недописанного файла внешней системой
    ПереместитьФайл(ВременныйФайл, ПутьКФайлу);

КонецПроцедуры

Вариант 2. Фиксация факта выгрузки через Регистр сведений

Если внесение изменений в структуру планов обмена нежелательно или конфигурация находится на поддержке без возможности редактирования метаданных плана обмена, можно использовать непериодический независимый РегистрСведений (например, ВыгруженныеДокументы).

Важное архитектурное правило: Не следует добавлять признак (флаг) «Выгружен» в сам документ ЧекККМ. Запись признака в документ при выгрузке приведет к повторной перезаписи объекта, изменению версии данных, блокировкам таблиц и лишним коллизиям в кассовой смене. Всегда выносите статус выгрузки в отдельный регистр сведений.

Структура регистра сведений:

  1. Измерение: Документ (Тип: ДокументСсылка.ЧекККМ).
  2. Ресурс: ДатаВыгрузки (Тип: Дата).

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


Функция ПолучитьНевыгруженныеЧеки(ПериодОтбора) Экспорт

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

    Запрос.УстановитьПараметр("ПериодОтбора", ПериодОтбора);
    
    Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

После успешной записи документов в XML выполняется пакетная запись ссылок в регистр сведений с помощью объекта РегистрСведенийНаборЗаписей.

Формирование XML: Потоковая запись vs СериализаторXDTO

В зависимости от требований внешней системы к структуре XML-файла применяются два подхода:

  1. Быстрая выгрузка через СериализаторXDTO: Если принимающая система способна обрабатывать XML произвольной структуры или схему 1С, сериализация всего объекта (включая шапку и табличные части Товары, Оплата) одной строкой через СериализаторXDTO.ЗаписатьXML() является самой производительной.
  2. Потоковая запись через ЗаписьXML: Если принимающая сторона ожидает строго определенный формат тегов, используется объект ЗаписьXML с методами ЗаписатьНачалоЭлемента, ЗаписатьАтрибут, ЗаписатьТекст и ЗаписатьКонецЭлемента. Потоковая запись в отличие от ДокументDOM не перегружает оперативную память сервера при больших объемах данных.

Посмотрим на пример ручной потоковой выгрузки необходимых реквизитов чека:


ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ПутьКФайлу, "UTF-8");
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("Receipts");

Для Каждого Стр Из ТаблицаЧеков Цикл
    ЧекОбъект = Стр.Ссылка.ПолучитьОбъект();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("Receipt");
    ЗаписьXML.ЗаписатьАтрибут("Number", Строка(ЧекОбъект.Номер));
    ЗаписьXML.ЗаписатьАтрибут("Date", Формат(ЧекОбъект.Дата, "ДФ=yyyy-MM-ddTHH:mm:ss"));
    ЗаписьXML.ЗаписатьАтрибут("Sum", Строка(ЧекОбъект.СуммаДокумента));
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("Items");
    Для Каждого СтрТовар Из ЧекОбъект.Товары Цикл
        ЗаписьXML.ЗаписатьНачалоЭлемента("Item");
        ЗаписьXML.ЗаписатьАтрибут("Code", Строка(СтрТовар.Номенклатура.Код));
        ЗаписьXML.ЗаписатьАтрибут("Name", Строка(СтрТовар.Номенклатура.Наименование));
        ЗаписьXML.ЗаписатьАтрибут("Quantity", Строка(СтрТовар.Количество));
        ЗаписьXML.ЗаписатьАтрибут("Price", Строка(СтрТовар.Цена));
        ЗаписьXML.ЗаписатьКонецЭлемента(); // Item
    КонецЦикла;
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Items
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Receipt
КонецЦикла;

ЗаписьXML.ЗаписатьКонецЭлемента(); // Receipts
ЗаписьXML.Закрыть();

Настройка автоматического запуска каждые 15 минут

Для выполнения экспорта по расписанию используется объект конфигурации РегламентноеЗадание:

  1. В ветке метаданных Общие > Регламентные задания добавляем новое задание (например, ВыгрузкаЧековККМ).
  2. В свойствах задания указываем процедуру общего модуля (модуль должен иметь флаг Сервер).
  3. Настраиваем Расписание: вкладка Дневное > Повторять каждые: 900 секунд (15 минут).
  4. Убеждаемся, что для информационной базы включена блокировка регламентных заданий (если база файловая, потребуется отдельный сеанс для выполнения заданий; в клиент-серверном варианте запуск выполняется службой кластера 1С).

Важные практические нюансы

  1. Атомарность записи файлов: Внешний скрипт или сервис-интегратор может попытаться прочитать XML в момент его записи платформой 1С. Чтобы исключить ошибку чтения битого файла, всегда выполняйте выгрузку во временный файл (например, с расширением .tmp), а после завершения метода ЗаписьXML.Закрыть() переименовывайте его в целевой .xml.
  2. Архивация чеков ККМ: В типовых конфигурациях (1С:Розница, 1С:УТ, 1С:ERP) при закрытии кассовой смены чеки могут архивироваться (очищаются табличные части) или удаляться с формированием свернутого документа ОтчетОРозничныхПродажах. Если внешняя система должна получать детализацию по позициям чека, выгрузка должна отрабатывать оперативно в течение смены до выполнения архивации.
  3. Идентификаторы ссылочных типов: При стандартной сериализации в XML ссылки на номенклатуру передаются в виде GUID. Если внешняя система сторонней разработки не знает внутренних идентификаторов 1С, явно выгружайте понятные поля для сопоставления: Артикул, Штрихкод или Код.
← На главную