При разработке собственного механизма адресного хранения на складе часто возникает вопрос: как правильно спроектировать структуру данных и как отражать операции размещения и изъятия товара из ячейки? Рассмотрим типичную ситуацию: разработчик создал регистр сведений для привязки номенклатуры к ячейке и столкнулся с проблемой при написании кода для удаления этой привязки.
Проанализируем исходный подход, выявим его ключевые недостатки и разберем, как реализовать такую задачу более корректно, а также какие готовые инструменты для этого есть в типовых конфигурациях 1С.
В исходной задаче была предложена следующая структура объектов:
Склад, Номенклатура.Ячейка.Основная проблема этой архитектуры кроется в структуре регистра сведений. Поскольку измерениями являются Склад и Номенклатура, система обеспечивает уникальность записей именно по этой связке. На практике это означает, что для одной номенклатуры в рамках одного склада может быть указана только одна ячейка.
Это серьезное ограничение. На реальном складе один и тот же товар часто хранится в нескольких ячейках: например, основная палета стоит в одной ячейке, а несколько коробок для быстрой отгрузки — в другой. Предложенная структура не позволяет отразить такую ситуацию.
Автор задал конкретный вопрос: что писать в коде, если пользователь выбрал действие «Убрать»? На форуме был предложен вариант:
Движение.Ячейка = Справочники.Ячейки.ПустаяСсылка();
Хотя автор принял это решение, оно является не совсем корректным с точки зрения идеологии регистров. Этот код не удаляет запись из регистра. Он оставляет запись о связке Склад + Номенклатура, но в качестве ячейки указывает пустое значение. Это может привести к "замусориванию" регистра и неверной логике в отчетах. Вы будете видеть, что товар где-то числится, но его ячейка не определена.
Правильный подход — полное удаление записи из регистра. Если товар убирают из ячейки, то факт его привязки должен исчезнуть. Поскольку регистр подчинен документу-регистратору, управлять записями нужно через набор записей или менеджер записи.
Рассмотрим, как должен выглядеть код в обработке проведения документа.
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Очищаем существующие движения документа, чтобы избежать дублей
Движения.РазмещениеВЯчейках.Записать();
// Создаем набор записей для добавления новых данных
НаборЗаписей = Движения.РазмещениеВЯчейках;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Если ТекСтрокаТовары.Действие = Перечисления.ДействияСЯчейкой.Разместить Тогда
// Если действие "Разместить", добавляем новую запись в регистр
Движение = НаборЗаписей.Добавить();
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Ячейка = ТекСтрокаТовары.Ячейка;
ИначеЕсли ТекСтрокаТовары.Действие = Перечисления.ДействияСЯчейкой.Убрать Тогда
// Если действие "Убрать", мы должны найти и удалить существующую запись.
// При текущей архитектуре (одна ячейка на товар) достаточно просто НЕ добавлять новую запись,
// т.к. старая будет удалена при очистке движений документа, если этот же документ ее и создал.
// Но более универсальный способ — использовать менеджер записи для удаления.
МенеджерЗаписи = РегистрыСведений.РазмещениеВЯчейках.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Склад = Склад;
МенеджерЗаписи.Номенклатура = ТекСтрокаТовары.Номенклатура;
// Читаем запись по измерениям
МенеджерЗаписи.Прочитать();
// Если запись существует, удаляем ее
Если МенеджерЗаписи.Выбран() Тогда
МенеджерЗаписи.Удалить();
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Записываем только те движения, которые были добавлены (для действия "Разместить")
НаборЗаписей.Записать();
КонецПроцедуры
Этот код более правильный, но он все еще работает в рамках flawed architecture. Давайте разберем, как можно улучшить саму структуру.
Чтобы решить проблему "один товар — одна ячейка", необходимо изменить саму архитектуру хранения данных.
Чтобы разрешить хранение одного товара в нескольких ячейках, нужно сделать уникальным ключ, включающий саму ячейку. Для этого перенесем поле Ячейка из ресурсов в измерения.
Новая структура регистра РазмещениеВЯчейках:
Склад, Номенклатура, Ячейка.Теперь уникальной будет связка «Склад + Номенклатура + Ячейка», что позволяет для одной и той же номенклатуры создать несколько записей с разными ячейками. Это уже гораздо ближе к реальным потребностям склада.
Если кроме факта размещения нужно отслеживать и количество товара в каждой ячейке, то регистр сведений — неподходящий инструмент. Для учета остатков предназначен регистр накопления вида «Остатки».
Правильная структура для учета остатков в ячейках:
Склад, Номенклатура, Ячейка (а также Характеристика, Серия, если требуется).Количество.При проведении документа «РазмещениеВЯчейке» нужно будет формировать движения с видом «Приход» или «Расход» по этому регистру, увеличивая или уменьшая остаток товара в конкретной ячейке.
Прежде чем создавать собственную систему, стоит изучить возможности типовых конфигураций, таких как «1С:Управление торговлей 11». В них уже встроены мощные и гибкие механизмы складского учета.
Это самый простой режим. Его суть — закрепить за номенклатурой основное место хранения. Система не следит за остатками в ячейках, а лишь предоставляет информацию кладовщику, где обычно лежит тот или иной товар. Это упрощает поиск, но не является полноценной системой WMS.
Это полноценная WMS-система, которая ведет точный учет остатков товаров в разрезе каждой ячейки. Для ее работы необходимо включить ордерную схему документооборота на складе.
Приходный ордер на товары, Расходный ордер на товары). Именно они формируют движения по регистру накопления остатков в ячейках. Система может автоматически генерировать задания на размещение и отбор, подбирая оптимальные ячейки на основе их характеристик (размер, грузоподъемность) и заданных правил.Вывод: Попытка создать собственную простую систему адресного хранения — полезное упражнение, но оно чревато архитектурными ошибками. В большинстве случаев гораздо эффективнее и надежнее использовать встроенные механизмы типовых конфигураций, которые уже продуманы, протестированы и поддерживаются фирмой «1С».