При разработке систем учета материальных ценностей (например, мобильных телефонов, выданных сотрудникам) начинающие разработчики часто сталкиваются с проблемой: данные в отчетах "накапливаются", и срез последних показывает не только актуальные на текущий момент сведения, но и устаревшие записи. Рассмотрим, почему это происходит, и проанализируем наиболее эффективные способы решения этой задачи в среде 1С:Предприятие.
Прежде всего, разберем механику работы периодического регистра сведений. В 1С РегистрСведений хранит состояние данных в разрезе уникальной комбинации измерений. Если в вашем регистре в качестве измерений установлены Сотрудник и IMEI, то запись за январь (Сотрудник А + Телефон 1) и запись за февраль (Сотрудник А + Телефон 2) — это две разные записи по разным измерениям. С точки зрения системы, Телефон 1 все еще числится за сотрудником, так как по нему не было новой записи, которая бы "перекрыла" старую (например, запись, где этот телефон переходит к другому человеку или списывается).
Если ваша задача состоит в том, чтобы новый документ "аннулировал" все предыдущие назначения и устанавливал только те, что указаны в его табличной части, мы имеем дело с логикой снимков (Snapshot), которая не является нативной для регистра сведений. Выясним, как реализовать требуемое поведение.
Это наиболее правильный архитектурный подход с точки зрения методологии 1С. Вместо того чтобы каждый месяц переписывать список всех телефонов у сотрудника, мы будем фиксировать только факты изменения состояния. Проанализируем структуру такой системы:
Телефоны, где будем хранить марку, модель и IMEI. Это позволит избежать дублирования строк и ошибок ввода.Телефон (тип Ссылка на справочник).Сотрудник.При такой структуре один телефон в один момент времени может принадлежать только одному сотруднику. Как только мы записываем в регистр по конкретному телефону нового владельца, старая запись автоматически перестает попадать в СрезПоследних, так как период новой записи больше. Для фиксации возврата телефона на склад можно создать специального служебного сотрудника "Склад" или использовать ресурс с типом Булево (Выдан/Сдан).
Для учета ТМЦ часто целесообразнее использовать РегистрНакопления с видом "Остатки". Посмотрим на преимущества этого метода. Документ, регистрирующий выдачу, может делать два вида движений:
Проанализируем пример кода в процедуре ОбработкаПроведения для такого документа:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// 1. Очищаем старые остатки по сотруднику
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| УчетТелефоновОстатки.Телефон КАК Телефон,
| УчетТелефоновОстатки.КоличествоОстаток КАК Количество
|ИЗ
| РегистрНакопления.УчетТелефонов.Остатки(&МоментВремени, Сотрудник = &Сотрудник) КАК УчетТелефоновОстатки";
Запрос.УстановитьПараметр("МоментВремени", МоментВремени());
Запрос.УстановитьПараметр("Сотрудник", Сотрудник);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующая() Цикл
Движение = Движения.УчетТелефонов.ДобавитьРасход();
Движение.Период = Дата;
Движение.Сотрудник = Сотрудник;
Движение.Телефон = Выборка.Телефон;
Движение.Количество = Выборка.Количество;
КонецЦикла;
// 2. Записываем новые данные из табличной части
Для Каждого Стр Из ТабличнаяЧастьТелефоны Цикл
Движение = Движения.УчетТелефонов.ДобавитьПриход();
Движение.Период = Дата;
Движение.Сотрудник = Сотрудник;
Движение.Телефон = Стр.Телефон;
Движение.Количество = 1;
КонецЦикла;
КонецПроцедуры
Этот подход гарантирует, что в любой момент времени отчет по остаткам покажет только те телефоны, которые были указаны в последнем проведенном документе.
Если бизнес-процесс требует именно ежемесячного ввода "ведомости" и вы не хотите менять структуру регистра, можно программно управлять набором записей. Основная проблема автора темы была в том, что старые записи оставались "активными". Чтобы этого избежать, нужно перед записью новых данных "закрывать" старые.
Рассмотрим алгоритм действий:
СрезПоследних по данному сотруднику.Однако есть более простой способ получить данные "как в документе" без сложной логики движений — это запрос к самому регистру с фильтром по периоду или регистратору. Если бухгалтер вводит документ один раз в месяц, мы можем найти последний документ за месяц и выбрать все его записи из регистра сведений:
ВЫБРАТЬ
Регистр.Сотрудник,
Регистр.Телефон,
Регистр.IMEI
ИЗ
РегистрСведений.ЗакрепленныеТелефоны КАК Регистр
ГДЕ
Регистр.Период В (
ВЫБРАТЬ МАКСИМУМ(Т.Период)
ИЗ РегистрСведений.ЗакрепленныеТелефоны КАК Т
ГДЕ Т.Период <= &НужнаяДата
)
Проанализировав ситуацию, можно дать следующие советы по улучшению системы:
Сотрудник должен быть единственным измерением, а список телефонов должен храниться либо в ресурсе (если телефон один), либо в подчиненном справочнике.Номенклатура или ОсновныеСредства. Это обеспечит целостность данных и позволит строить отчеты в разрезе моделей без риска опечаток.Выбор конкретного метода зависит от масштабов системы. Для простого учета достаточно Решения 1 с правильной расстановкой Измерений и Ресурсов. Для серьезного инвентарного учета лучше использовать Решение 2 с регистром накопления.