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

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

В процессе разработки отчетов или обработок в системе 1С:Предприятие (особенно в таких конфигурациях, как УПП или Комплексная автоматизация 1.1) программисты часто сталкиваются с необходимостью классифицировать документ поступления. Проблема заключается в том, что документ ПоступлениеТоваровУслуг является универсальным и может содержать данные о материальных ценностях, услугах, работах и даже оборудовании. Разберем подробно, как правильно и эффективно определить, что именно пришло по документу, и какие подводные камни нас ожидают.

Метод 1. Анализ заполненности табличных частей

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

Проанализируем ситуацию, когда нам нужно быстро понять состав документа. Мы можем использовать следующий алгоритм: если заполнена только одна таблица, мы присваиваем документу соответствующий статус. Рассмотрим пример кода:


КолТоваров = ОбъектДокумента.Товары.Количество();
КолУслуг = ОбъектДокумента.Услуги.Количество();
КолОборудования = ОбъектДокумента.Оборудование.Количество();

Если КолТоваров > 0 И КолУслуг = 0 И КолОборудования = 0 Тогда
    // Это чисто товарное поступление
    Результат = "Товары";
ИначеЕсли КолУслуг > 0 И КолТоваров = 0 И КолОборудования = 0 Тогда
    // Чистое поступление услуг
    Результат = "Услуги";
ИначеЕсли КолТоваров > 0 И КолУслуг > 0 Тогда
    // Смешанный тип документа
    Результат = "Смешанный";
Иначе
    // Обработка исключений (например, только тара или оборудование)
    Результат = "Прочее";
КонецЕсли;

Важно: этот метод имеет существенный недостаток. Пользователь может по ошибке внести услугу (например, "Доставка") в табличную часть Товары, выбрав соответствующий элемент справочника Номенклатура. В этом случае проверка табличных частей выдаст неверный результат.

Метод 2. Проверка типа номенклатуры (Best Practice)

Более надежный способ — проанализировать содержимое строк. У каждого элемента справочника Номенклатура есть реквизит ТипНоменклатуры (или ВидНоменклатуры, в зависимости от версии и настроек конфигурации), который представляет собой перечисление: Товар, Услуга, Работа или Набор.

Рассмотрим, как реализовать проверку по типам номенклатуры, обходя все строки документа. Проанализируем пример функции, которая определяет «товарную сущность» документа:


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

В этом примере мы учитываем, что в табличной части Товары технически может оказаться номенклатура с признаком Услуга = Истина. Это позволяет избежать ошибок классификации при некорректном вводе данных пользователем.

Метод 3. Использование запросов для массовой обработки

Если нам нужно обработать список документов (как в случае автора темы), использование объектной модели (получение каждого документа и перебор строк) крайне неэффективно с точки зрения производительности. Выясним, как решить задачу одним запросом.

Посмотрим на пример запроса, который определяет наличие товаров и услуг в документе, используя объединение таблиц:


ВЫБРАТЬ
    Док.Ссылка КАК Ссылка,
    МАКСИМУМ(ЕСТЬNULL(Типы.ЭтоТовар, ЛОЖЬ)) КАК СодержитТовары,
    МАКСИМУМ(ЕСТЬNULL(Типы.ЭтоУслуга, ЛОЖЬ)) КАК СодержитУслуги
ИЗ
    Документ.ПоступлениеТоваровУслуг КАК Док
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            Товары.Ссылка КАК Ссылка,
            ИСТИНА КАК ЭтоТовар,
            ЛОЖЬ КАК ЭтоУслуга
        ИЗ
            Документ.ПоступлениеТоваровУслуг.Товары КАК Товары
        ГДЕ
            НЕ Товары.Номенклатура.Услуга
            
        ОБЪЕДИНИТЬ ВСЕ
        
        ВЫБРАТЬ
            Услуги.Ссылка,
            ЛОЖЬ,
            ИСТИНА
        ИЗ
            Документ.ПоступлениеТоваровУслуг.Услуги КАК Услуги
    ) КАК Типы ПО Док.Ссылка = Типы.Ссылка
ГДЕ
    Док.Ссылка В (&МассивСсылок)
СГРУППИРОВАТЬ ПО
    Док.Ссылка

Данный подход позволяет за один вызов к базе данных получить флаги содержимого для всех документов в списке. Это значительно ускоряет работу обработки.

Метод 4. Анализ через регистры накопления

Иногда самым точным способом является анализ движений, которые сделал документ. Если документ ПоступлениеТоваровУслуг сделал движения по регистру ПартииТоваровНаСкладах (в УПП) или ТоварыНаСкладах, значит, в нем точно были материальные ценности. Если же движения есть только в регистре Затраты или Закупки (по номенклатуре с типом "Услуга"), то это услуга.

Преимущества этого метода:

  1. Отражает фактическое влияние документа на учет.
  2. Игнорирует ошибки заполнения табличных частей, если они не привели к движениям по складу.
  3. Позволяет сразу отсечь "Работы", которые могут учитываться на складе, от "Услуг", которые списываются на затраты сразу.

Метод 5. Учет «Вида операции» документа

Как было верно замечено в обсуждении, реквизит ВидОперации может дать подсказку. Например:

Подводные камни: Услуги vs Работы

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

Итоговые рекомендации

Для создания надежной обработки мы рекомендуем комбинированный подход:

  1. Использовать запрос для получения данных, чтобы не перегружать систему.
  2. Проверять не только факт заполнения табличных частей, но и свойство Услуга (или ТипНоменклатуры) у каждой позиции.
  3. Обязательно предусмотреть ветку Иначе для случаев, когда документ заполнен некорректно (например, пустые обе ТЧ) или содержит смешанный состав, чтобы вывести предупреждение пользователю.

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

← На главную