Полное закрытие периода (постановка)

Материал из GedeminWiki
Перейти к: навигация, поиск

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

Решение

Необходимо получить «чистую» базу, то есть базу без складских документов и проводок созданных ранее даты закрытия периода. Есть три пути:

  1. копирование исходной базы А в файл базы Б, и последующее удаление данных старше указанной даты закрытия периода с базы Б, затем перенос складских и бухгалтерских остатков на дату закрытия с базы А на Б
  2. формирование базы Б – копии базы данных А, но без данных, и последующий перенос на базу Б складских и бухгалтерских остатков на дату закрытия, а также документов и проводок созданных после даты закрытия периода с базы А (+ все остальные необходимые справочники и нескладские документы)
  3. копирование исходной базы А в файл базы Б (в смысле делаем backup-restore в базу Б), последующее формирование бухгалтерских и складских остатков на дату закрытия периода прямо на базе Б, удаление складских документов и проводок с базы Б созданных до даты закрытия периода.

Предполагается давать возможность выбора:

  • типов закрываемых документов, то есть документов, по которым будет формироваться складской и бухгалтерский остаток, и из которых затем будут удаляться устаревшие записи.
  • бухгалтерских аналитик и складских признаков карточки по которым будет происходить группировка остатков. Например, при формировании складского остатка нам не нужны признаки карточки привязывающие движение к конкретной позиции документа (USR$INV_ADDLINEKEY – ссылка на документ прихода). При формировании бухгалтерского остатка будем использовать все признаки бухгалтерской проводки кроме привязки к конкретному документу.

Под датой {CLOSEDATE} закрытия периода понимается дата, начиная с которой на новой базе будут идти уже не сгруппированные документы и проводки. Расчет бухгалтерского и складского остатков будет производиться на дату {CLOSEDATE - 1}

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

CREATE TABLE DB_CLOSEHISTORY ??? (
  id dintkey,
  databasepath varchar(2048),
  server varchar(255),
  user varchar(31),
  password varchar(31),
  closedate date
)


Разовьем 3-ий способ закрытия периода.

  1. Заходим в базу Б и запускаем процедуру закрытия периода
  2. Формируется бухгалтерский остаток на дату {CLOSEDATE - 1}
  3. Удаляем проводки, по которым сформировался остаток
  4. Сохраняем бухгалтерский остаток как проводки на дату {CLOSEDATE - 1}
  5. Формируем складской остаток на дату {CLOSEDATE - 1}
  6. Перепривязываем складские карточки
  7. Удаляем документы, по которым сформировался складской остаток
  8. Сохраняем складской остаток в документе прихода INV_DOCUMENT с датой равной {CLOSEDATE - 1}
  9. Перестроить оперативную информацию по проводкам в таблице AC_ENTRY_BALANCE (при удалении и вставке проводок появится много лишних записей)
  10. Установим генератор {generator name} в значение {CLOSEDATE} (предполагается в дальнейшем использовать эту дату при построении комплексных отчетов по данным находящимся в новой и старой базе)

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

Бухгалтерские остатки формируются путем группировки всех проводок за период предшествующий дате закрытия периода. Сформированные бухгалтерские остатки предполагается вставлять в таблицу AC_ENTRY (+ AC_RECORD) как проводки на дату закрытия периода. Удаление устаревших проводок проходит просто, необходимо только правильно ограничить запрос на удаление (дата, типы документов). При удалении устаревших документов удаляются и складские карточки созданные позициями этих документов, но более новые карточки из движения могут ссылаться на эти, удаляемые, карточки (по полю PARENT). Значит необходима перепривязка новых (с датой создания >= {CLOSEDATE}) складских карточек к карточкам созданным документом INV_DOCUMENT, то есть к карточкам по сформированному складскому остатку.

SELECT
 m_less.movementdate,
 c_less.ID,
 c_less.PARENT,
 c_less.DOCUMENTKEY,
 c_less.FIRSTDOCUMENTKEY,
 c_less.FIRSTDATE,
 m_more.movementdate,
 c_more.ID,
 c_more.PARENT,
 c_more.DOCUMENTKEY,
 c_more.FIRSTDOCUMENTKEY,
 c_more.FIRSTDATE
FROM
 inv_card c_less
 JOIN inv_card c_more ON c_more.parent = c_less.id
 JOIN inv_movement m_less ON m_less.cardkey = c_less.id
 JOIN inv_movement m_more ON m_more.cardkey = c_more.id
WHERE
 m_less.movementdate < :closedate
 AND m_more.movementdate >= :closedate

Во всех карточках c_more полученных из этого запроса надо переставить поле PARENT на карточки по документу INV_DOCUMENT. Соответствие карточек определяется на основе выбранных пользователем актуальных признаков складских карточек. Те же самые изменения произвести с записями m_more, но изменять надо поле CARDKEY.

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

EXECUTE BLOCK
(
  closedate DATE = :closedate
)
AS
 DECLARE VARIABLE mid INTEGER;
 DECLARE VARIABLE cardkey INTEGER;
 DECLARE VARIABLE dockey INTEGER;
 DECLARE VARIABLE headdockey INTEGER;
 DECLARE VARIABLE rel_name_head VARCHAR(31);
 DECLARE VARIABLE rel_name_line VARCHAR(31);
 DECLARE VARIABLE Sql VARCHAR(1024);
BEGIN
 FOR
   SELECT
     m.id,  m.cardkey, m.documentkey
   FROM
     inv_movement m
   /*WHERE
     m.movementdate < :closedate */
   ORDER BY
     m.movementdate DESC, m.id DESC
   INTO
     :mid, :cardkey, :dockey
 DO
 BEGIN
   SELECT
     line.relationname, head.relationname
   FROM
     gd_document doc
     JOIN gd_documenttype t ON t.id = doc.documenttypekey
     JOIN at_relations line ON line.id = t.linerelkey
     JOIN at_relations head ON head.id = t.headerrelkey
   WHERE
     doc.id = :dockey
   INTO
     :rel_name_line, rel_name_head;

   SELECT
     parent
   FROM
     gd_document
   WHERE
     id = :dockey
   INTO
     :headdockey;

   -- удалим позицию документа
   Sql = 'DELETE FROM ' || :rel_name_line || ' WHERE documentkey = ' || CAST(:dockey AS VARCHAR(20));
   EXECUTE STATEMENT Sql;
   DELETE FROM gd_document WHERE id = :dockey;

   -- если шапка стала пустой удалим и ее
   Sql = 'SELECT h.documentkey FROM ' || :rel_name_head || ' h WHERE h.documentkey = ';
   Sql = Sql || CAST(:headdockey AS VARCHAR(20)) || ' AND NOT EXISTS (SELECT l.documentkey FROM ';
   Sql = Sql || :rel_name_line ||' l WHERE l.masterkey = h.documentkey )';
   FOR
     EXECUTE STATEMENT Sql
     INTO :dockey
   DO
   BEGIN
     Sql = 'DELETE FROM ' || :rel_name_head || ' WHERE documentkey = ' || CAST(:dockey AS VARCHAR(20));
     EXECUTE STATEMENT Sql;
     DELETE FROM ac_entry WHERE (documentkey = :dockey) OR (masterdockey = :dockey) OR (usr$gs_document = :dockey);
     DELETE FROM gd_document WHERE id = :dockey;
   END
 END
END

Глобальные отчеты и получение «закрытых» данных

После полного закрытия периода может возникнуть необходимость в построении отчета, или получении данных одновременно с текущей рабочей базы, и уже закрытой архивной базы (баз). Предполагается создать новый бизнес-объект {TgdcDatabaseCloseHistory} представляющий информацию из таблицы {DB_CLOSEHISTORY}. Через функцию объекта:

function GetDatabaseList(ActualDateBegin, ActualDateEnd: TDateTime): TStringList

, указав значения дат по которым необходимо построить отчет или получить данные, можно будет получить список баз данных (с путями) которые необходимо задействовать в данном отчете. Список баз будет отсортирован по дате закрытия, начиная с самой старой базы. Получив список закрытых баз программист может получить данные с внешней базы либо при помощи создания транзакции к внешней базе, либо при помощи конструкции EXECUTE STATEMENT, которая, начиная с FB 2.5 может обращаться к внешней базе.

[FOR] EXECUTE STATEMENT <query_text> [(<input_parameters>)]
  [ON EXTERNAL [DATA SOURCE] <connection_string>]
  [WITH {AUTONOMOUS | COMMON} TRANSACTION]
  [AS USER <user_name>]
  [PASSWORD <password>]
  [WITH CALLER PRIVILEGES]
  [INTO <variables>]
Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Инструменты