На главную   На главную   Форумы Новости Документация Скачать Купить  
Регистрация  
Система Allegro
Oб Allegro Характеристики Пример конфигурации Документация База ошибок Развитие
Версия для печати К списку книг Вернуться к оглавлению Предыдущий параграф Следующий параграф
Поиск по книге

Глава 10. БУХГАЛТЕРСКИЕ ПРОВОДКИ

Автоматическое проведение документов, системная таблица ACC_TURN

Так как хранимые процедуры шаблонов в любой момент предоставляют нам необходимый «кусок» журнала проводок, остается лишь сохранить этот набор в таблице проводок. Все бухгалтерские проводки хранятся в таблице ACC_TURN. Если мы хотим « перепровести» уже существующий документ (например, после внесения в него изменений), то нужно сначала удалить старые проводки по данному документу, а затем вставить новые проводки, поставляемые хранимой процедурой шаблона. Программа делает все это автоматически путем вызова хранимой процедуры <имя_главной_таблицы _документа>_CHANGED. Эта хранимая процедура создается программой автоматически, и ее текст зависит от того, какие шаблоны имеет конкретный тип документа.

Пример хранимой процедуры, осуществляющей перепроведение документов типа «Ручная операция»:

CREATE PROCEDURE GAAP_CHANGED(ID INTEGER)
AS
DECLARE VARIABLE OPER_DATE DATE;
DECLARE VARIABLE PERIOD_START DATE;
DECLARE VARIABLE LAYER_ID INTEGER;
DECLARE VARIABLE DEBIT DECIMAL(18,2);
DECLARE VARIABLE CREDIT DECIMAL(18,2);
DECLARE VARIABLE MIN_DATE DATE;
BEGIN
/*Текст данной процедуры создан системой Allegro автоматически.*/
/*Не меняйте этот текст. Ваши изменения могут быть утеряны*/
  /*Выбираем дату начала периода*/
  SELECT START_DATE FROM PERIOD_PROPERTIES INTO :PERIOD_START;
  /*Удаление старых проводок*/
  DELETE FROM ACC_TURN WHERE DOC_ID = :ID;
  /*Проверка на равенство дебета кредиту в каждом слое на каждую дату*/
  FOR SELECT OPER_DATE, LAYER_ID, SUM(DEBIT) DEBIT, SUM(CREDIT) CREDIT
  FROM GAAP_TEMPLATE(NULL,NULL,:ID) T, ACC
  WHERE OPER_DATE>=:PERIOD_START AND T.ACC_ID = ACC.ACC_ID AND
                ACC.NO_BALANCE = 0
  GROUP BY OPER_DATE, LAYER_ID INTO :OPER_DATE, :LAYER_ID, :DEBIT, :CREDIT
  DO
  BEGIN
    IF (DEBIT <> CREDIT) THEN  EXCEPTION NO_BALANCE;
    /*Запоминание саммой ранней даты в составе операции*/
    IF ((MIN_DATE IS NULL) OR (MIN_DATE > OPER_DATE)) THEN
      MIN_DATE = OPER_DATE;
  END
  /*Добавление новых проводок*/
  INSERT INTO ACC_TURN (OP_DATE, ACC_ID, LAYER_ID, OBJECT_ID, TEMPLATE_ID,
                        DOC_ID, IS_CREDIT, DEBIT, CREDIT,
                        QUANTITY_DEBIT, QUANTITY_CREDIT)
              SELECT OPER_DATE, ACC_ID, LAYER_ID, OBJECT_ID, TEMPLATE_ID,
                        DOC_ID, IS_CREDIT, SUM(DEBIT), SUM(CREDIT),
                        SUM(QDEBIT), SUM(QCREDIT)
              FROM GAAP_TEMPLATE(NULL,NULL,:ID)
              WHERE OPER_DATE >= :PERIOD_START
              GROUP BY OPER_DATE, ACC_ID, LAYER_ID, OBJECT_ID, TEMPLATE_ID,
                        DOC_ID, IS_CREDIT;
  /*Сдвиг даты расчетов*/
  IF (NOT (MIN_DATE IS NULL)) THEN
    EXECUTE PROCEDURE SET_CALCULATIONS(:MIN_DATE);
END

Обратим внимание, что при проведении документа однотипные записи по счетам «сжимаются» с помощью агрегатных функций SUM(). Это сделано для уменьшения количества строк в таблице проводок ACC _TURN и для придания операциям более компактного и читабельного вида. Например, два десятка парных записей при проведении накладной «Продажи» сожмется до 13 результирующих записей в таблице проводок. Одна запись будет содержать общую сумму, начисленную покупателю, одна запись - сумму начисленных доходов, одна – сумму начисленных товарных расходов, а 10 остальных – суммы, списанные со счета «Товары», раздельно для каждого товара.

Итак, для перепроведения конкретного документа какого-то типа , нам достаточно вызвать хранимую процедуру <имя_главной _таблицы_документа>_CHANGED, передав в нее входным параметром ID документа. Например, так можно перепровести «Продажи товара», документ с ID = 11031:

execute procedure sale_changed(11031);

Разработчик для вызова этой команды может воспользоваться также процедурой встроенного языка:

procedure MakeEntries(const MainTableName: string; doc_id: integer;
                                      ATransaction: TIBTransaction);

Эта процедура просто вызывает ту же SQL команду в контексте определенной транзакции. В качестве параметров нужно передать название главной таблицы документа, внутренний номер ID документа, который следует перепровести, и указатель на компонент транзакции.

Так как все действия по перепроведению документов производятся на сервере , это происходит без ощутимых временных затрат (практически мгновенно ). Все проводки хранятся в таблице ACC_TURN - сердце бухгалтерской системы. Таблица организована таким образом, чтобы максимально быстро извлекать из нее все интересующие нас сведения, например, любой Т-счет. Для этого она снабжена специальными индексами:

PRIMARY KEY (OP_DATE,ACC_ID,LAYER_ID,OBJECT_ID,TEMPLATE_ID,DOC_ID,IS_CREDIT)
CREATE INDEX X_ACC_TURN_DOC_ID ON ACC_TURN(DOC_ID);
CREATE INDEX X_ACC_T_ASC ON ACC_TURN(ACC_ID,OP_DATE,DOC_ID,TEMPLATE_ID,LAYER_ID);
CREATE DESCENDING INDEX X_ACC_T_DESC ON ACC_TURN(ACC_ID,OP_DATE,DOC_ID,
  TEMPLATE_ID,LAYER_ID);

Системная таблица ACC_TURN


Название поля Тип данных Назначение
OP_DATE DATE Дата проводки
ACC_ID INTEGER Внутренний ACC_ID счета
LAYER_ID INTEGER Внутренний LAYER_ID слоя
OBJECT_ID INTEGER Внутренний ID объекта аналитики
TEMPLATE_ID INTEGER Внутренний TEMPLATE_ID шаблона операции
DOC_ID INTEGER Внутренний ID конкретного проведенного документа
IS_CREDIT SMALLINT Тип записи 0 – запись в дебет 1 – запись в кредит
DEBIT DECIMAL(18,2) Сумма дебет
CREDIT DECIMAL(18,2) Сумма кредит
QUANTITY_DEBIT DECIMAL(18,3) Количество дебет
QUANTITY_CREDIT DECIMAL(18,3) Количество кредит

Обратим внимание на то, что бухгалтерские записи хранятся « вертикально» в англо-американском стиле «смешанных» проводок: по одной записи на каждый счет. Такое хранение проводок значительно ускоряет получение Т-счетов, всевозможный анализ и интерпретацию данных. Например, мы с помощью одного SQL-запроса быстро (за доли секунды при десятках тысяч проводок) можем получить текущую себестоимость всех имеющихся товаров на складах по каждому товару:

select g.id, o.short_name,
  (sum(a.debit)-sum(a.credit))/(sum(a.quantity_debit)-sum(a.quantity_credit))
from  acc_turn a, goods g, object_names o
where a.object_id = o.object_id and  g.id = o.object_id
group by g.id, o.short_name,
having sum(a.quantity_debit)-sum(a.quantity_credit) <> 0


Система Allegro. Руководство разработчика Наверх