[firebase-br] Recalculo de saldo (Trigger)

andre conrado acf.andre em gmail.com
Seg Set 26 10:28:00 -03 2011


Ok amigo, seu problema é de lógica, então vamos a ela:

Na sua TRIGGER o primeiro passo está correto, isto é, vc obtém o saldo
somando as colunas a CREDITO, DEBITO e SALDO_INI. Até está razoável,
mas eu faria um diferente, pense o seguinte:

- Quanto o primeiro lançamento for inserido ou alterado o campo saldo
este lançamento precisa ser atualizado, o que não ocorre em seu
código, já que o FOR SELECT só está tratando os registros posteriores.
  Então está faltando depois dos SELECTs de somatório o seguinte linha:
     NEW.SALDO = BANCOSALDO + NEW.CREDITO - NEW.DEBITO;
     (Imagino o campo SALDO não esteja sendo calculado via aplicação)

Vamos agora ao conteúdo do FOR SELECT:

1º - Sua rotina está colocando no SALDO o valor total dos créditos e
débitos até o lançamento atual, isso desconsidera os créditos e
débitos posteriores que interferem nos cálculos posteriores.
2º - Quanto o UPDATE é executado uma nova chamada a TRIGGER será
gerada, o que fará com que nova chamada seja gerada até que não acha
mais lançamento. Sendo assim, as atualização não precisariam ser
chamadas dentro de um FOR SELECT.

Tá ficando confuso néh, fiz está colocações para complexidade do
rotina acima, então vamos começar todo de novo. Tente assim, e me diga
se funciona:

// TRIGGER para Atualiza do SALDO atual

CREATE OR ALTER trigger trg_saldo_up_before for lanc
active after before position 2

AS
DECLARE VARIABLE LANCAMENTO INTEGER;
DECLARE VARIABLE SALDOANTERIOR INTEGER;

BEGIN

    /* Primeiro passo, obter o saldo anterior, se existirem
lançamentos anteriores então obtenho o saldo do último lançamento
       caso contrário obtenho o saldo inicial do banco */

    IF (EXISTS(SELECT 0 FROM LANC WHERE LANC_ID <  NEW.LANC_ID)) THEN
        SELECT FIRST 1 SALDO FROM LANC ORDER BY LANC_ID DESC INTO
:SALDOANTERIOR;
    ELSE
        SELECT SALDO_INI FROM CADBANCO WHERE CCONTA = NEW.CCONTA INTO
:SALDOANTERIOR;

    // Calcula o saldo atual

    NEW.SALDO = SALDOANTERIOR + NEW.CREDITO - NEW.DEBITO;

END

// TRIGGER para atualizar o SALDO dos lançamento subsequentes

CREATE OR ALTER trigger trg_saldo_up_after for lanc
active after update position 2

AS
DECLARE VARIABLE LANCAMENTO INTEGER;
DECLARE VARIABLE SALDOANTERIOR INTEGER;

BEGIN

    // Localiza o próximo lançamento

    SELECT FIRST 1 LANC_ID FROM LANC WHERE LANC_ID >  NEW.LANC_ID
ORDER BY LANC_ID INTO :LANCAMENTO;

    // Simula a alteração do próximo lançamento para que o FIREBIRD
gere uma nova chamada a TRIGGER de atualização do SALDO

    UPDATE LANC SET CREDITO = CREDITO WHERE LANC_ID = :LANCAMENTO;

END


Dúvida ou críticas? Não fique com elas... rsrs

abçs




Mais detalhes sobre a lista de discussão lista