Блокировка периода (постановка)
From GedeminWiki
Изначально, блокировка периода распространялась на все документы и всех пользователей системы. Позже, была добавлена возможность исключить некоторые группы пользователей из блокировки и, наконец, мы добавили возможность исключать некоторые типы документов. Но, период, а точнее дата, до которой запрещается изменять записи в БД, остается фиксированной константой.
Contents |
Существующий механизм блокировки периода
За определение: подпадает конкретный тип документа под блокировку или нет, отвечает процедура gd_p_exclude_block_dt, которая возвращает 1, если переданный идентификатор типа документа не блокируется и 0 в противном случае. Процедура формируется в окне Tgd_dlgOptions при выборе типов документов исключаемых из блокировки. Системными составляющими механизма блокировки периода являются генераторы gd_g_block и gd_g_block_group. Первый хранит дату, до которой документы считаются заблокированными, а второй -- битовую маску групп пользователей, на которых распространяется блокировка. Механизм реализуется с помощью 12-ти триггеров, по три на каждую из четырех таблиц: gd_document, ac_entry, ac_record и inv_movement. Существующий триггер блокировки периода выглядит следующим образом. В случае нарушения условия блокировки вызывается исключение gd_e_block.
Данный механизм имеет следующие ограничения:
- Нельзя устанавливать разные периоды для разных типов документов;
- Нельзя устанавливать разные периоды для разных групп пользователей;
- Дата блокировки задается фиксированной константой.
Новый механизм блокировки
Предлагается модифицировать механизм блокировки периода следующим образом:
Интерфейс пользователя
Хранение информации о блокировке
Информацию о параметрах блокировки планируется хранить в таблице GD_BLOCK_RULE.
Метаданные
CREATE PROCEDURE gd_p_block (DocDate DATE, DocType INTEGER)
AS
DECLARE VARIABLE IG INTEGER;
BEGIN
...
// такой блок кода повторяется для каждой группы типов документов
IF (DocType IN (12345, 67890, ...)) THEN
BEGIN
// если блокировка распространяется на все группы
// пользователей без исключений, то проверим дату
// и, при нарушении, вызовем исключение
IF (DocDate < date `01.01.2001`) THEN
EXCEPTION gd_e_block;
// если указаны группы, на которые не распространяется блокировка,
// сначала проверяем дату, а затем не попадает ли пользователь
// в список исключенных групп
IF (DocDate < date `01.01.2001`) THEN
BEGIN
SELECT ingroup FROM gd_user WHERE ibname = CURRENT_USER
INTO :IG;
IF (BIN_AND(12345, :IG) = 0) THEN
EXCEPTION gd_e_block;
END
// для ФБ 2.0 можно попробовать избежать лишних чтений из таблицы
// и кэшировать значение битовой маски в контекстной переменной
IF (DocDate < date `01.01.2001`) THEN
BEGIN
IF (RDB$GET_CONTEXT(`USER_SESSION`, `INGROUP`) = ``) THEN
BEGIN
SELECT ingroup FROM gd_user WHERE ibname = CURRENT_USER
INTO :IG;
RDB$SET_CONTEXT(`USER_SESSION`, `INGROUP`, :IG);
END ELSE
IG = RDB$GET_CONTEXT(`USER_SESSION`, `INGROUP`);
IF (BIN_AND(12345, :IG) = 0) THEN
EXCEPTION gd_e_block;
END
// если при задании условия блокировки использовались метапеременные
// то вычисляем соответствующую им дату. Например, задана переменная
// ПредМесяц
M = EXTRACT(MONTH FROM CURRENT_DATE) - 1;
IF (M = 0) THEN M = 12;
IF (DocDate < CAST('01.' || M || '.' || EXTRACT(YEAR FROM CURRENT_DATE) AS DATE)) THEN
EXCEPTION gd_e_block;
END
...
END
