Как реализовать классификацию контрагентов, контроль отрицательных остатков и отчет по неликвидам в 1С

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

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

1. Классификация контрагентов запросом («Покупатель», «Поставщик», «Прочие»)

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

Разберем логику построения запроса. Для высокой производительности мы не соединяем справочник Контрагенты напрямую с таблицами документов, так как это вызывает сканирование таблиц документов и замедляет работу СУБД. Оптимальным решением является использование виртуальных таблиц оборотов регистров (например, регистров взаиморасчетов, закупок и продаж) с передачей параметров периода непосредственно в саму виртуальную таблицу.

Посмотрим на пример текста запроса:


ВЫБРАТЬ
    СпрКонтрагенты.Ссылка КАК Контрагент,
    ВЫБОР
        КОГДА ЕСТЬNULL(ОборотыПродажи.КоличествоОборот, 0) > 0 И ЕСТЬNULL(ОборотыЗакупки.КоличествоОборот, 0) > 0
            ТОГДА "Покупатель и поставщик"
        КОГДА ЕСТЬNULL(ОборотыПродажи.КоличествоОборот, 0) > 0
            ТОГДА "Покупатель"
        КОГДА ЕСТЬNULL(ОборотыЗакупки.КоличествоОборот, 0) > 0
            ТОГДА "Поставщик"
        ИНАЧЕ "Прочие"
    КОНЕЦ КАК КатегорияКонтрагента
ИЗ
    Справочник.Контрагенты КАК СпрКонтрагенты
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ОборотыПродажи
        ПО СпрКонтрагенты.Ссылка = ОборотыПродажи.Контрагент
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Закупки.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ОборотыЗакупки
        ПО СпрКонтрагенты.Ссылка = ОборотыЗакупки.Контрагент
ГДЕ
    НЕ СпрКонтрагенты.ЭтоГруппа

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

2. Контроль отрицательных остатков при проведении документов

Проанализируем ситуацию списания товара со склада. При проведении документа расхода необходимо проверить, не ушел ли остаток по какой-либо позиции в минус. В платформе 1С применяются две методики контроля: старая (проверка остатков до формирования движений) и новая (формирование движений с последующей проверкой отрицательного остатка).

Разберем по шагам реализацию проверки по новой методике:

  1. Записываем сформированные движения документа в регистр остатков с установкой флага Записывать = Истина.
  2. Выполняем запрос к виртуальной таблице Остатки регистра накопления с фильтром по номенклатуре документа и условием нахождения отрицательных значений: ЕСТЬNULL(ОстаткиТоваровОстатки.КоличествоОстаток, 0) < 0.
  3. Если в выборке есть строки, устанавливаем параметр Отказ = Истина и выводим пользователю подробное сообщение с указанием номенклатуры, склада и величины нехватки через объект СообщениеПользователю.

Посмотрим на пример программного кода в модуле документа:


// 1. Формируем и записываем движения
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.Записать();

// 2. Проверяем отрицательные остатки
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Остатки.Склад КАК Склад,
    |   Остатки.Номенклатура КАК Номенклатура,
    |   Остатки.КоличествоОстаток КАК Остаток
    |ИЗ
    |   РегистрНакопления.ОстаткиТоваров.Остатки(
    |       &МоментВремени,
    |       Номенклатура В (ВЫБРАТЬ РАЗЛИЧНЫЕ ТекНоменклатура.Номенклатура ИЗ Документ.РасходнаяНакладная.Товары КАК ТекНоменклатура ГДЕ ТекНоменклатура.Ссылка = &Ссылка)
    |   ) КАК Остатки
    |ГДЕ
    |   ЕСТЬNULL(Остатки.КоличествоОстаток, 0) < 0";

Запрос.УстановитьПараметр("МоментВремени", МоментВремени());
Запрос.УстановитьПараметр("Ссылка", Ссылка);

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    Отказ = Истина;
    
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = "Недостаточно товара " + Выборка.Номенклатура + " на складе " + Выборка.Склад + ". Отрицательный остаток: " + Формат(Выборка.Остаток, "ЧДЦ=3");
    Сообщение.УстановитьДанные(ЭтотОбъект);
    Сообщение.Сообщить();
КонецЦикла;

При использовании управляемых блокировок перед выполнением проверки обязательно устанавливается объект БлокировкаДанных с режимом РежимБлокировкиДанных.Исключительный, что предотвращает возникновение коллизий при параллельной работе пользователей.

3. Формирование отчета по неликвидным товарам

Выясним причину отнесения номенклатуры к неликвидам: это товары, которые фактически числятся на остатках склада, но по которым отсутствуют продажи за заданный промежуток времени (например, за последние 30, 60 или 90 дней).

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


ВЫБРАТЬ
    ОстаткиТоваров.Склад КАК Склад,
    ОстаткиТоваров.Номенклатура КАК Номенклатура,
    ОстаткиТоваров.КоличествоОстаток КАК ТекущийОстаток
ИЗ
    РегистрНакопления.ОстаткиТоваров.Остатки(&ПериодОстатков, ) КАК ОстаткиТоваров
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты(&НачалоПериодаПродаж, &КонецПериодаПродаж, , ) КАК ПродажиОбороты
        ПО ОстаткиТоваров.Номенклатура = ПродажиОбороты.Номенклатура
ГДЕ
    ОстаткиТоваров.КоличествоОстаток > 0
    И (ПродажиОбороты.КоличествоОборот ЕСТЬ NULL ИЛИ ПродажиОбороты.КоличествоОборот = 0)

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

← На главную