Регистры сведений на V7

Цель этой статьи – показать неочевидные, но довольно интересные возможности платформы V7. Изучив статью, вы научитесь создавать периодические зависимости от двух и более параметров (например, справочников), проводить документы будущей датой, проводить одним документом "регисты" на разные даты, создавать "прямые" (без промежуточных итогов) таблицы. Причем все это реализуется стандартными средствами V7 и работает как на DBF-, так и на SQL-базах.

автор статьи: Андрей Морев (Z1)
опубликовано: февраль 2003

Источник: http://hare.ru/

Цель этой статьи – показать неочевидные, но довольно интересные возможности платформы V7. Изучив статью, вы научитесь создавать периодические зависимости от двух и более параметров (например, справочников), проводить документы будущей датой, проводить одним документом "регисты" на разные даты, создавать "прямые" (без промежуточных итогов) таблицы. Причем все это реализуется стандартными средствами V7 и работает как на DBF-, так и на SQL-базах.

Для начала рассмотрим периодические значения в стандартном понимании V7.

Имеется некий справочник. У элемента справочника есть реквизит. Значение реквизита зависит от календарной даты. Такие реквизиты пользователь может редактировать в ручном режиме. Классический пример – справочник валют и реквизит Курс в типовых конфигурациях.

V7 также позволяет позиционировать значения периодических реквизитов с точностью до секунды (позиция документа) на оси времени. Для такого манипулирования надо использовать специальную функцию из модуля проведения документа УстановитьРеквизитСправочника().

Предположим, вам необходимо по каким-то причинам хранить изменения курсов валют с точностью до секунды и пятью десятичными разрядами. Немного изменив конфигурацию, вы без особого труда сделаете это.

Но периодические величины из учетных задач не всегда укладываются в такую схему. Попробуйте например реализовать на V7 три конкретных примера:

Пример #1. Несколько складов в разных городах. Затраты на перевозку товаров между скаладами А и Б зависят от склада А, склада Б и времени (в календарных днях), причем в терминах линейной алгебры матрица перевозок необязательно симметрична (затраты А -> Б не всегда равны затраты Б -> А). Диагональным элементам соответсвуют затраты на перемещение внутри конкретного склада.

Пример #2. Продажа бензина. Есть товар – бензин, есть "особые" клиенты. Цена продажи зависит от двух этих величин. Причем дискретность по времени – 1 секунда. (Вспомните период резкого изменения цен на бензин).

Пример #3.Есть поставщики, есть товары, есть склады в разных городах. Необходимо хранить затраты по доставке от конкретного поставщика до конкретного склада. Причем на некоторые товары затраты по доставке от конкретного поставщика на конкретный Склад могут быть разными.

Вы без особого труда можете и сами продолжить список примеров которые "плохо" ложатся на модель данных V7. (Решение примеров 1 и 3 приложены к статье, см. внизу страницы.)

Перед тем, как углубляться в техническую реализацию описанных проблем, давайте перечислим основные недостатки периодических реквизитов V7:

  1. Практически невозможно создать зависимость одной величины от двух и более величин;
  2. Все значения свалены в одну общую таблицу. Эта таблица индексирована, но всё равно является очень узким местом БД;
  3. Неудобно работать с периодическими величинами в запросах;
  4. Противоречивость во встроенном языке: недопустимо одновременное использование методов ИспользоватьДату и УстановитьЗначение, благолдатная почва для ошибок кодирования.
В новой версии V8 предлагается вместо периодических реквизитов использовать регистры сведений. Точно за терминологию не ручаюсь, но регистр сведеней – это таблица данных, сведений о каких-либо физических сущностях. Регистр состоих из:
  • Измерений (далее ИзмеренияСведений). Это, например, справочники.
  • Ресурсы (далее РесурсСведений ). В основном это числа, хотя и не обязательно.
Причем в регистре сведений неявно присутсвует время – в какой момент времени Ресурсы по выбранным измерениям начинают действовать.

В терминах теории множеств мы имеем функцию (записанную в табличном виде): отображение одного множества (измерения ) на другое множество (ресурсы).

И здесь возникает мысль – а ведь ничто не мешает нам отобразить модель Регистров сведений V8 на Регистры V7. Берем обычный регистр остатков и строим на его основе Регистр сведений.

ПсевдоРегистрСведений строится на v7 следующим образом :

  • Измерение (в терминах V8) соответсвует РеквизитуИзмеренияСведений (реквизит V7), далее ПсевдоИзмерение.
  • Ресурс (в терминах v8) соответсвует РесурсуСведений (реквизит V7), далее ПсевдоРесурс.
  • Псевдокомментарий – реквизит в терминах V7. Это комментарий или дополнительная информация о конкретном движении.
Причем для ПсевдоИзмерений мы всегда включаем флаг отбоора движений. ПсевдоРесурсы я всегда ставлю сначала (до) псевдоизмерений.

Вот мы и получили описание Регистра сведений на базе стандартной платформы V7.

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

Постулат #1. В качестве ИзмеренияСведений можно использовать свое "время".

Т.е мы можем в качестве измерения выбрать тип "дата" и по этому измерению менять значения как текущим числом, так и прошлым и/или будущим.

В качестве ПсевдоИзмерения времени можно и выбрать и справочник. Документ может формировать движения РегистраСведений будущей (или прошлой) датой. Один документ может формировать несколько движений РегистраСведений с разными датами.

Пример №1. Справочник Кварталы:

Элементы справочника
1кв_2001 года
2кв_2001 года
3кв_2001 года
4кв_2001 года
1кв_2002 года
2кв_2002 года
3кв_2002 года
4кв_2002 года
1кв_2003 года
2кв_2003 года
3кв_2003 года
4кв_2003 года

Теперь мы можем использовать справочник Кварталы как аналог Времени (это та же самая дата, но но уже с другим масштабом).

Пример #2. Выбираем в качестве ИзмеренияСведений тип "Дата" (в терминах V7). Мы можем делать движение документа как текущей датой, так и прошлой и/или будущей датой.

Классический пример регистр Остатков в этом случае будет выглядеть так:

Измерения псевдорегистра сведений
Товар
Склад
ДатаДвижения
Ресурсы псевдорегистра сведений
Количество
Сумма
Реквизиты псевдорегистра сведений
Комментарий

Конечно, к такому регистру будет нужно написать свои функции НачОстаток, Приход, Расход, КонОстаток – но дело того стоит.

Постулат #2. Никто не запрещает нам использовать несколько (более одного) Измерений Времени. Например. Операции с товаром – приход и расход. Первое псевдоизмерение времени (дата и время операции хранятся в самом документе, и отдельного измерения для них не нужно) есть время реального прихода или расхода товара, второе псевдоизмерение (тип "дата") есть время прихода или расхода товара по полному пакету документов.

При таком подходе по каждому псевдоизмерению времени будем иметь разные товарные остатки и разные материальные ведомости. Мне также кажется, что с таким подходом легче будут решаться распределение партий FIFO,LIFO. Имея два разных масштаба времени, мы сможем очень быстро получать обороты, используя фильтры по разным измерениям времени.

Постулат #3. Двойственность или даже тройственность РегистраСведений. РегистрСведений можно рассматривать с разных сторон:

  1. Это события, произошедшие в определенный момент времени (например, факты продажи товара);
  2. Это Ресурсы, которые начинают действовать с заданного момента времени (например, курс валюты);
  3. Это Ресурсы, действующие до определенного момента времени (например, срок годности товара или срок действия договора).
Причем, если мы имеем таблицу фактов, то случай (А) – это фактически OLAP-куб.

Постулат #4. Часто возникает мысль, а оправданы ли затраты – как машинные (внешняя память, время пересчета), так и человеческие (сдвиг точки актуальности или границы последовательности, более сложные алгоритмы вычислений остатков в зависимости от актуальности итогов, etc.) – на хранение и поддержку в актуальном состоянии промежуточных итогов.

Не является ли эти затраты лишними? Не проще ли, когда требуется расчитать тот или иной итог, просто вычислить его по отфильтрованной таблице базы данных?

Описанный выше регистр сведений не хранит промежуточных итогов, только движения. Значит, этот регистр можно рассматривать как обычную таблицу базы данных. А следовательно, можно строить выборки по этой таблице средствами самой базы данных (ADO, ODBC, XP, etc.).

Выводы.

Статья нам стандартный объект V7 "Регистр" под новым углом зрения. Изложенные выше идеи можно эффективно реализовывать в таких моделях данных, которые будут успешно "ложится" как на V7, так и на V8. Используя эти принципы для V7 можно создать более быстрые (и более понятные) алгоритмы обработки данных и расширить диапозон решаемых задач.

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

Приложение.

См. также приложенную конфигурацию.

Задача #1. Используется вспомогательный справочник ДельтаЦен. Структура справочника складов такова: первый уровень изображает город, второй уровень – конкретный склад в городе. Цены назначаются только для групп справочника (городов).

Для манипулирования ценами служит отчет "Цены_перемещений_между_складами". При добавлении новой группы справочника складов в отчете "Цены_перемещений_между_складами" необходимо нажать кнопку "+склад".

Задача #3. Есть регистр ЦеныПоставщика, документ ЦеныПоставщиков устанавливает цены на конкретную дату. Ну и отчет УзнатьЦену.


Приложенные ссылки

Начать дискуссию