← Назад к вопросам

Резервирование товара под клиента

2.3 Middle🔥 171 комментариев
#Конфигурации и типовые

Условие

Доработайте конфигурацию складского учёта — добавьте возможность резервирования товара под клиента.

Требования:

  1. Документ "РезервированиеТовара" с табличной частью (Номенклатура, Количество)
  2. Регистр накопления "РезервыТоваров" (измерения: Номенклатура, Контрагент)
  3. Отчёт "Наличие товаров":
    • Общий остаток на складе
    • Зарезервированное количество
    • Свободный остаток (доступно к продаже)

Контроль

При проведении документа расхода проверять, что количество не превышает свободный остаток.

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Архитектура решения

Решение состоит из трёх компонентов:

  1. Документ РезервированиеТовара — фиксирует резервирование
  2. Регистр РезервыТоваров — накапливает информацию о резервах
  3. Отчёт "Наличие товаров" — показывает доступность

1. Документ "РезервированиеТовара"

Структура

Документ: РезервированиеТовара
├── Реквизиты:
│   ├── Номер (Автонумерация)
│   ├── Дата
│   ├── Контрагент (Ссылка на Справочник.Контрагенты)
│   ├── Склад (Ссылка на Справочник.Склады)
│   └── Статус (Перечисление: Черновик, Активно, Отменено)
│
└── Табличная часть: Товары
    ├── Номенклатура
    ├── Количество
    └── ЕдиницаИзмерения

Код модуля

Процедура ПередПроведением(Отмена)
    
    // Проверка обязательных реквизитов
    Если ПустаяСтрока(Контрагент) Тогда
        Отмена = Истина;
        Сообщить("Укажите контрагента!");
        Возврат;
    КонецЕсли;
    
    Если Товары.Количество() = 0 Тогда
        Отмена = Истина;
        Сообщить("Добавьте товары!");
        Возврат;
    КонецЕсли;
    
    // Проверка на достаточность свободного товара
    Для Каждого СтрокаТовара Из Товары Цикл
        
        ОстатокТовара = ПолучитьОстатокТовара(СтрокаТовара.Номенклатура, Склад);
        Зарезервировано = ПолучитьЗарезервированноеКоличество(СтрокаТовара.Номенклатура);
        СвободноеКоличество = ОстатокТовара - Зарезервировано;
        
        Если СвободноеКоличество < СтрокаТовара.Количество Тогда
            Отмена = Истина;
            Сообщить(СтрокаТовара.Номенклатура + ": необходимо " + СтрокаТовара.Количество + " шт, свободно " + СвободноеКоличество + " шт.");
            Возврат;
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Функция ПолучитьОстатокТовара(Номенклатура, Склад)
    Запрос = Новый Запрос("SELECT SUM(Количество) КАК Остаток FROM ОстаткиТоваров WHERE Номенклатура = &Ном AND Склад = &Склад");
    Запрос.УстановитьПараметр("Ном", Номенклатура);
    Запрос.УстановитьПараметр("Склад", Склад);
    Результат = Запрос.Выполнить();
    Возврат Результат.Пусто() ? 0 : Результат.Первая().Остаток;
КонецФункции

Функция ПолучитьЗарезервированноеКоличество(Номенклатура)
    Запрос = Новый Запрос("SELECT SUM(Количество) КАК Зарезервировано FROM РезервыТоваров WHERE Номенклатура = &Ном");
    Запрос.УстановитьПараметр("Ном", Номенклатура);
    Результат = Запрос.Выполнить();
    Возврат Результат.Пусто() ? 0 : Результат.Первая().Зарезервировано;
КонецФункции

2. Регистр накопления "РезервыТоваров"

Структура

РегистрНакопления: РезервыТоваров (тип: Остатки)
├── Измерения:
│   ├── Номенклатура
│   ├── Контрагент
│   └── ДокументРезервирования
│
└── Ресурсы:
    └── Количество

Правило проведения документа

// При проведении РезервированиеТовара:
Для Каждого СтрокаТовара Из Товары Цикл
    
    Движение = ДвижениеРегистра.РезервыТоваров.Добавить();
    Движение.Период = Дата;
    Движение.Номенклатура = СтрокаТовара.Номенклатура;
    Движение.Контрагент = Контрагент;
    Движение.ДокументРезервирования = Ссылка;
    Движение.Количество = СтрокаТовара.Количество;
    
КонецЦикла;

3. Контроль при расходе товара

Модуль документа РасходТоваров

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

4. Отчёт "Наличие товаров"

Процедура ПриКомпоновке(ДокументРезультат, ДанныеПараметров, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    ТаблицаРезультата = Новая ТаблицаЗначений;
    ТаблицаРезультата.Колонки.Добавить("Номенклатура");
    ТаблицаРезультата.Колонки.Добавить("Склад");
    ТаблицаРезультата.Колонки.Добавить("ОбщийОстаток", Новый ОписаниеТипов("Число"));
    ТаблицаРезультата.Колонки.Добавить("Зарезервировано", Новый ОписаниеТипов("Число"));
    ТаблицаРезультата.Колонки.Добавить("СвободныйОстаток", Новый ОписаниеТипов("Число"));
    
    Запрос = Новый Запрос("SELECT DISTINCT Номенклатура, Склад, SUM(Количество) КАК Остаток FROM ОстаткиТоваров GROUP BY Номенклатура, Склад");
    ДанныеОстатков = Запрос.Выполнить().Выгрузить();
    
    Для Каждого СтрокаОстатка Из ДанныеОстатков Цикл
        
        Зарезервировано = ПолучитьЗарезервированное(СтрокаОстатка.Номенклатура);
        
        НоваяСтрока = ТаблицаРезультата.Добавить();
        НоваяСтрока.Номенклатура = СтрокаОстатка.Номенклатура.Наименование;
        НоваяСтрока.Склад = СтрокаОстатка.Склад.Наименование;
        НоваяСтрока.ОбщийОстаток = СтрокаОстатка.Остаток;
        НоваяСтрока.Зарезервировано = Зарезервировано;
        НоваяСтрока.СвободныйОстаток = СтрокаОстатка.Остаток - Зарезервировано;
        
    КонецЦикла;
    
    РезультатДокумент = Новый ТабличныйДокумент;
    РезультатДокумент.Вывести(ТаблицаРезультата);
    ДокументРезультат.Вставить(РезультатДокумент);
    
КонецПроцедуры

Процесс использования

1. Менеджер создаёт РезервированиеТовара
   ├─ Выбирает контрагента
   ├─ Добавляет товары
   └─ Проводит (система проверяет наличие)

2. Остатки фиксируются в РезервыТоваров
   └─ ОбщийОстаток - Зарезервировано = СвободноеКоличество

3. При расходе система проверяет:
   ├─ Расход по резервированию → используется зарезервированное
   └─ Обычный расход → проверяется свободное

4. Отчёт показывает:
   ├─ Общее количество
   ├─ Зарезервировано
   └─ Свободно к продаже

Это решение предотвращает перепродажу и обеспечивает полный контроль над резервированием.