Блокировка периода (постановка)

From GedeminWiki

Jump to: navigation, search

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

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
Personal tools