Hare.ru @ Коллективный разум / Hare.ru @ Дикое место

Архив hare.ru 
Мысли, конвертированные в текст

Концептуальные работы


Все статьи раздела

Альтернатива Последовательности документов. Концепция решения.

Никита Зайцев (WildHare) (где-то в 2001)

Если Вы спросите любого 1С-программиста, что он думает по поводу проведения документов задним числом, то, скорее всего, услышите сдавленное рычание и что-нибудь про отрывание рук тем пользователям, которые.. А если не услышите — значит, Вам попался неопытный 1С-программист.

В самом деле, что может быть хуже? Расход превышает приход, на складе возникает отрицательный остаток, а тщательно налаженный и просчитанный партионный учет улетает к чертовой бабушке. Что делать?

Самый простой способ заключается в административном (в техническом смысле слова) запрете проводить документы задним числом. В самом деле, ведь “мёртвые бастарды не могут наследовать трон“. Но далеко не каждый заказчик согласится с такой точкой зрения программиста. И будет прав — дело не только и не столько в раздолбайстве персонала, вечно теряющего одни документы и неожиданно находящего другие, потерянные месяц назад. Многие бизнес-процессы построены таким образом, что проведение документов задним числом является их неотъемлемой частью — например, когда поставщик назначает отпускные (а для нас закупочные) цены на партию товара по итогам продаж этой партии.

Так что запретить не получится. Если программист не сможет гарантировать корректности нужных заказчику расчетов, заказчик не будет вступать в прения, а просто наймет другого программиста. И будет прав.

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

Казалось бы, проблема решена. Но не все так просто — восстановление последовательности на практике означает тотальное перепроведние всех входящих в последовательность документов, начиная со “сбойного” и заканчивая самым последним по времени. А если “сбойный” документ располагается в начале прошлого года? Если за этот год в базу было занесено полмиллиона документов? Если у нас есть сотня поставщиков, и 99 работают с нами как люди, а сотый — как самый настоящий нелюдь, но он самый важный для нас и “сбойные” накладные от него поступают каждую неделю? Нам приходится постоянно перепроводить и пересчитывать сотни и тысячи (а особо везучим и десятки тысяч) ни в чем не повинных документов. Программисты изобретают самые невероятные способы облегчить себе жизнь, создавая инструменты для сколь угодно хитрого автоматического восстановления последовательностей. Последовательность явно не годится на роль универсального лекарства. Вот если бы её можно было привязать не к движениям регистра, как таковым, а к движениям регистра по конкретному набору измерений, было бы намного удобнее.

Попробуем временно забыть про существование объекта “Последовательность” и вооружиться инструментом под названием “собственные руки”. Что получается?

  • Прежде всего определим “ключевое” измерение регистра, по которому нам нужно контролировать движения (обычно, это самое верхнее измерение). Убедимся, что это справочник, потому что для не-справочников методику еще не выдумали.
  • Допустим, мы нашли справочник “Клиенты”. Создадим у него новый периодический реквизит типа “Документ”. Назовем его, например, Граница. Выставим у реквизита опцию “Изменяется документами” и отключим опцию “Ручное изменение”. Можно вставить этот реквизит в форму, но в режиме R/O — пользователи не должны иметь возможности его модифицировать.
  • Пишем глобальную функцию примерно такого рода:

    Функция Проверка (Конт) Экспорт
       Граница=Конт.Клиент.Граница.Получить(РабочаяДата());
       Если СравнитьДокиПоВремени(Граница,Конт.ТекущийДокумент())=1 Тогда
          Сообщить("ай-ай! последовательность нарушена");
          Возврат 0;
       Иначе
          Возврат 1;
       КонецЕсли;
    КонецФункции

    Функция СравнитьДокиПоВремени() тупо сравнивает два документа по дате/времени и ее код я не привожу ввиду полной тривиальности.

  • Теперь дописываем несколько строк в модуль документа:

    Процедура ОбработкаПроведения ()
       Если Проверка(Контекст)=0 Тогда
          СтатусВозврата(0);
          Возврат;
       КонецЕсли;

       // тут собственно проведение документа

       УстановитьРеквизитСправочника(Клиент,"Граница",
       ТекущийДокумент(),ДатаДок,,,););
    КонецПроцедуры

  • Чтобы не маяться с ручным восстановлением нашей микропоследовательности, делаем служебную обработку, которая находит все документы по нужному клиенту за некий период и перепроводит их в нужном порядке. Чтобы не тратить время на предварительную отмену проведения, можно через некий флаг (константу, глобальную переменную и т.п.) передавать в процедуру проверки указание всегда возвращать единицу, если проведение было инициировано не пользователем, а служебной обработкой. Нужно будет сделать еще десяток вещей, описание которых я пропущу ввиду наличия у моих гипотетических читателей хорошего воображения и богатого профессионального опыта.
В этом примере выбран самый жесткий вариант поведения системы, когда проведение задним числом работает только через специальную обработку (возможно, только с санкции администратора БД), а все прочие попытки блокируются. Но никто не запрещает реализовать и более лояльную к пользователю схему — когда факт нарушения последовательности просто где-то фиксируется, а потом всплывает в некоторый момент. Это дело вкуса (или ТЗ), лично я предпочитаю не давать пользователю возможности сделать что-то не так, чем потом успешно преодолевать последствия этого “не так”.

Что мы имеем в итоге? Проведение документа задним числом требует пересчета уже не всей базы “от забора и до обеда”, а только некоторой части документов. Приведенный код является реализацией самого простого случая, ведь “ключевых” измерений регистров, на которые влияет проведение документа, обычно несколько (клиент, товар, фирма, etc.) и приведенная схема даст выигрыш отнюдь не в любом случае. Но в некоторых случаях (и это проверено практикой) использование механизма “умных” последовательностей дает неплохой эффект.

А где тут грабли, спросит вдумчивый читатель? Ведь не может же быть, чтобы технологическое ограничение платформы обходилось столь элементарным образом. И действительно, грабли присутствуют.

Хранение в периодическом реквизите справочника ссылок на документы, где этот справочник фигурирует, с точки зрения оптимальности структуры данных выглядит далеко не лучшим образом: поскольку 1С хранит все значения всех периодических реквизитов в таблице 1sconst, мы создаем в базе еще одну таблицу немеряного размера, в пару к таблице 1sjourn. С этим можно бороться, время от времени вычищая из истории значений те документы, которые “сданы в архив”, т.е. не должны больше перепроводится. Но это означает, что нам нужно предусмотреть аварийный механизм перепроведения и для этих документов тоже (ведь хоть один из них в свое время обязательно извлекут из архива). Но даже и в этом случае проблема перегрузки базы служебными данными будет весьма острой, особенно в случае нескольких параллельных микропоследовательностей. Если в документе сто товаров, то ссылка на документ запишется в сотню элементов справочника. Таблица 1sjourn распухнет на одну запись, а таблица 1sconst — на сотню записей. Ничего себе арифметика?

Не получилось ли так, что мы променяли шило даже не мыло, а на другое шило? Все зависит от ситуации. Ни одна задача не решается в общем виде, и ни одно универсальное решение не обходится без дополнительных издержек. Просто в одном случае выгоднее одно решение, а в другом — другое. Есть еще ситуации, которые называются “Уловка-22”, но мне кажется, что проблема восстановления последовательностей к таковым все же не относится ;-)

Партнеры:


Также может быть интересно:

Канал Россия 1 на http://spbtvonline.ru/
   
 Сайт поддерживается за счет партнеров:
:::... Сайт содержит архив двух версий hare.ru Карта сайта