Как правильно реализовать уникальность заказа маркетплейса в 1С 7.7

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

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

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

В отличие от справочников, где реквизит можно сделать индексируемым (флаг «Сортировка») и контролировать его уникальность, табличные части документов в 1С 7.7 хранятся в общей таблице DT*, где индексы строятся только по системным полям (ID документа, номер строки). Прямая попытка СУБД проконтролировать уникальность значения в строке невозможна средствами конфигуратора. Разберем основные стратегии решения этой задачи.

Решение 1: Проверка через Таблицу Значений (ТЗ) при проведении

Этот метод является наиболее «простым» и не требует изменения структуры базы данных. Мы перехватываем момент проведения документа и анализируем все существующие записи в базе. Проанализируем алгоритм:

  1. В модуле документа в процедуре ОбработкаПроведения создаем объект «Запрос» или используем выгрузку табличных частей.
  2. Собираем все ID заказов из текущего документа.
  3. Ищем эти ID в табличных частях других проведенных документов того же типа.

Пример кода для реализации такой проверки:


Процедура ОбработкаПроведения()
    // Создаем таблицу значений для текущих строк
    ТЗ_Текущие = СоздатьОбъект("ТаблицаЗначений");
    ВыгрузитьТабличнуюЧасть(ТЗ_Текущие, "ID_Заказа");
    
    // Удаляем пустые ID, если они допустимы
    ТЗ_Текущие.ВыбратьСтроки();
    Пока ТЗ_Текущие.ПолучитьСтроку() = 1 Цикл
        Если ПустаяСтрока(ТЗ_Текущие.ID_Заказа) = 1 Тогда
            ТЗ_Текущие.УдалитьСтроку();
        КонецЕсли;
    КонецЦикла;

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

Решение 2: Использование вспомогательного справочника («Теневой индекс»)

Чтобы избежать медленного перебора всех документов при каждой проверке, можно создать справочник ИндексыЗаказов. Выясним причину эффективности этого метода: поиск по справочнику в 1С 7.7 работает значительно быстрее благодаря штатным индексам.

Логика работы:

  1. Создаем справочник ИндексыЗаказов, где Наименование — это ID заказа маркетплейса.
  2. В справочнике устанавливаем флаг «Контроль уникальности».
  3. При записи или проведении документа программно пытаемся создать элемент в этом справочнике.

Если элемент с таким ID уже существует, 1С выдаст ошибку или мы сами обработаем это через НайтиПоНаименованию(). Это гарантирует уникальность даже в случае параллельной работы нескольких менеджеров.

Решение 3: Реализация через Графы Отбора

Рассмотрим подробнее использование механизма «Графа отбора». Если включить реквизит табличной части в графу отбора, система создаст запись в таблице 1SCRDOC. Это фактически создает индекс, связывающий значение реквизита с документом.

Посмотрим на пример поиска через графу отбора:


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

Решение 4: Прямые SQL-запросы (для SQL-версий 1С)

Если ваша база работает на MS SQL Server и вы используете внешнюю компоненту 1С++, это самый производительный способ. Мы можем выполнить прямой запрос к таблице DT* (строки документов), минуя объектную модель 1С. Выясним, как это выглядит на практике:


ТекстЗапроса = "
|SELECT TOP 1
|    ParentID as [Док $Документ]
|FROM
|    $ДокументСтроки.Резерв
|WHERE
|    $ДокументСтроки.Резерв.ID_Заказа = :НужныйID
|    AND ParentID <> :ТекущийДок
|";
// Выполнение через ODBCRecordset даст ответ за миллисекунды

Практические советы по автоматизации процесса

Проанализируем ситуацию с человеческим фактором. Часто дубли возникают из-за того, что менеджеры «перекидывают» заказы между складами вручную. Чтобы минимизировать ошибки, рекомендуется:

Подведем итог: наиболее надежным и быстрым методом для 1С 7.7 является сочетание вспомогательного справочника (для жесткого контроля уникальности) и проверки в ОбработкеПроведения. Это позволит сохранить целостность данных при обмене с Wildberries и защитит базу от дублирования резервов.

← На главную