calcular juros e multa dentro de um select

Delphi

14/08/2006

Não sei se dar pra fazer, mas preciso disto:
tenho um Select:
[color=red:0c47c42c1c]SQL.add(´Select NUMCHEQUE, DATACADASTRO, VALOR, NUMAGENCIA, NUMCONTA,NOMEBANCO, NOMECLIENTE from CHEQUE where SITU IS NULL AND DATACADASTRO < :pData´);[/color:0c47c42c1c]

[color=blue:0c47c42c1c]Tenho duas Variaves publicas: vJuros, vMulta : Real;
vJuros := 2 ¬; apos 5 dias de vencido
vMulta 5 ¬ apos 30 dias de vencido[/color:0c47c42c1c]

o que preciso: Apos o Campo DATACADASTRO
Criar um novo campo tipo valJuros recebendo o valor dos juros mais multa sobre o VALOR CHEQUE. então preciso de uma forma de ver quantos dias esta atrasado tipo (NOW - DATACADASTRO) e se for maior que 30 acrescentar multa a cada trinta dias mais os juros por dia de vencido.

em Tempo: so posso cobrar juros apos 5 dias de vencido e multa a cada 30 dias.

Acho complicado, mas como em programação dar pra fazer qualquer coisa, espero que alguem me ajude com este select.
OBrigado
Claudio D´Pinho


Dpinho

Dpinho

Curtidas 0

Respostas

Dmalta

Dmalta

14/08/2006

Claudio,

Você não mencinou qual o banco de dados que está usando, então vou assumir que está usando SQL Server, só pra dar um exemplo. Dependendo do BD haverá variações menores de sintaxe e nomes de funções.

Vamos lá, você só precisa usar CASE para estabelecer uma condição linha-a-linha, uma função ou operador para ver a diferença entre duas datas em dias (ignorando horas e minutos) - DATEDIFF - e uma função ou operador para truncar um valor numérico para o menor inteiro (tirando os decimais) - FLOOR.

SELECT
   numcheque, datacadastro, valor, numagencia, numconta, nomebanco, nomecliente,
   CASE WHEN DATEDIFF(d, datacadastro, GETDATE()) > 5 THEN 
      (0.02 * valor) * DATEDIFF(d, datacadastro, GETDATE())
   ELSE
      0.0
   END AS Juros,
   CASE WHEN DATEDIFF(d, datacadastro, GETDATE()) > 30 THEN 
      (0.05 * valor) * FLOOR(DATEDIFF(d, datacadastro, GETDATE()) / 30)
   ELSE
      0.0
   END AS Multa
FROM
   cheque

Adapte os detalhes da sintaxe ao seu SGBD.

A propósito, esse tópico não deveria estar num fórum de banco de dados ao invés de Delphi?

Espero que ajude a resolver seu problema.

Um abraço, :wink:


GOSTEI 0
Dpinho

Dpinho

14/08/2006

Utiliso Interbase 7

Caso eu truncar o valor não teria problemas, pois preciso dos decimais
Outra coisa, os valores dos juros e multa são gravados em variavel, porque estão cadastradas na tabela parametro, aja visto o usuario poder alterar estes valores dependendo dos indices praticados por estado


GOSTEI 0
Dmalta

Dmalta

14/08/2006

Claudio,

Veja bem, a função de truncar números que estou usando é pra pegar o número de MESES dividindo o intervalo de dias por 30. Por exemplo, em 65 dias você tem 2 meses (65/2=2,17 -> 2 meses).

Quanto às taxas serem variáveis, não tem mistério, é só fazer um JOIN com a tabela de alíquotas e usar as colunas dessa tabela no lugar dos literais que eu coloquei no código anterior.

Entendeu?

Um abraço,


GOSTEI 0
Dpinho

Dpinho

14/08/2006

Claudio, Veja bem, a função de truncar números que estou usando é pra pegar o número de MESES dividindo o intervalo de dias por 30. Por exemplo, em 65 dias você tem 2 meses (65/2=2,17 -> 2 meses). Quanto às taxas serem variáveis, não tem mistério, é só fazer um JOIN com a tabela de alíquotas e usar as colunas dessa tabela no lugar dos literais que eu coloquei no código anterior. Entendeu? Um abraço,


Meu Caro, agradeço muito sua ajuda ate agora, mas acho que vou abusar um pouco mais

so tenho as duas variaveis, não esta em uma tabela, toda configuração é feita em arquivo txt, mas ate aqui tudo bem, posso colocar em uma tabela.

testei sua dica mas estou tendo um problema com o ´WHEN´ a mensagem é: token unknown -line 1, char 90 when


GOSTEI 0
Dpinho

Dpinho

14/08/2006

Alterando meu select ja consigo recuperar a quantidade de dias em atraso:

[color=red:9e0e8841d2]SQL.add(´Select NUMCHEQUE, DATACADASTRO, VALOR, cast(current_date - datacadastro as Integer) dias_vencer , NUMAGENCIA, NUMCONTA,NOMEBANCO, NOMECLIENTE from CHEQUE where SITU IS NULL AND DATACADASTRO < :pData´);[/color:9e0e8841d2]

Agora preciso de um campo com o valor dos juros e outro com o valor da multa e um terceiro com o valot total

Lembrando a mensagem inicial que o percentual de juros e multa esta em um variavel recuperada de um arquivo INI
Meu banco é interbase e accho que não aceita Case when

Ajude ai pessoal


GOSTEI 0
Dpinho

Dpinho

14/08/2006

Alguem pode me ajudar
tambem esta dando um erro na clausula case when, diz que when não pode ser utilizado


GOSTEI 0
Dmalta

Dmalta

14/08/2006

Oi Claudio!

Mostre o seu código SQL pra gente dar uma olhada :!:


GOSTEI 0
Dpinho

Dpinho

14/08/2006

Oi Claudio! Mostre o seu código SQL pra gente dar uma olhada :!:



[color=red:c09266de7b] With SQLtemp do //CHEQUE EM ABERTO
begin
Close;
SQL.Clear;
SQL.add(´Select NUMCHEQUE, DATACADASTRO, VALOR, cast(current_date - datacadastro as Integer) dias_vencer,´);
// SQL.Add(´CASE dias_vencer > 5 then (0.02 * valor) juros end´);
SQL.Add(´NUMAGENCIA, NUMCONTA,NOMEBANCO, NOMECLIENTE from CHEQUE where SITU IS NULL AND DATACADASTRO < :pData´);
ParamByName(´pData´).Asdate := now;
open;
end;[/color:c09266de7b]

Amigo, Tentei utilizar o seu codigo SQL e não deu certo porque esta retornando um Erro no when, fiz o codigo acima e esta retornando a quantidade de dias, agora preciso fazer o calculo do valor do juros e colocar em uma celular.
tenho que pegar a quantidade de dias e ver se tem mais de cinco e calcular um campo com os juros de 2 por cento que retonar de um arquivo ini para uma variavel, apos isto tenho que verificar a cada 30 dias e mais uma celular com a multa de 5 por cento a cada trinta dias
Estes valores de 2 por cento e 5 por cento retonar em uma variavel de um arquivo ini.

Utilizo Delphi 7 com Interbase 7, conecção com tecnologia DBExpress
ClientDataset, DataSetprovider, SQLQuery, DAtaSource, DBGrid

Agradeço sua ajuda


GOSTEI 0
Dmalta

Dmalta

14/08/2006

Veja se funciona esse código na sua aplicação:
SELECT
   numcheque, datacadastro, valor,
   CAST(CURRENT_DATE - datacadastro AS INTEGER) dias_vencer,
   CASE WHEN CAST(CURRENT_DATE - datacadastro AS INTEGER) > 5 THEN
      (0.02 * valor) * CAST(CURRENT_DATE - datacadastro AS INTEGER)
   ELSE
      0
   END juros,
   numagencia, numconta,nomebanco, nomecliente
FROM CHEQUE
WHERE situ IS NULL AND datacadastro < :pData

Um abraço,


GOSTEI 0
Dpinho

Dpinho

14/08/2006

Retorna o erro:

Project Optical,exe raised exception class EDatabaseError message ´Token unknowm - line 3, char4 WHEN´. process stopped.Use step or Run to continue


GOSTEI 0
Dmalta

Dmalta

14/08/2006

Claudio,

:( Lamento mas tenho uma má notícia pra te dar: acontece que o [i:62d1100043]Interbase 7 ainda não suporta a sintaxe CASE[/i:62d1100043], apesar de ser parte do padrão SQL ANSI a muitos anos.

O Firebird 1.5 já aceita CASE, por outro lado... :?

A única forma de fazer isso no IB7 que eu posso imaginar é criando suas próprias funções UDF em DLLs.

Um abraço,


GOSTEI 0
Cristiano Duarte

Cristiano Duarte

14/08/2006

Eai caros amigos, vou postar minha solução. ficou muito bom e já converti para 2 casas decimais.

Regra de negócio
Percentual de Multa: 0.02
Percentual de Juros: 0.01


declare @codAluno int; set @codAluno = '81653'
declare @codTipoMatricula int; set @codTipoMatricula = '9'
select distinct ContasReceberParcela, cr.ContasReceberValor,
CASE
WHEN DiasAtraso > 0 THEN Cast((cr.ContasReceberValor * 0.02) as Decimal(7,2))
ELSE 0 END AS Multa,
CASE
WHEN cr.ContasReceberJuros IS NULL THEN Cast((cr.ContasReceberValor * 0.01 / 30 * DiasAtraso)as Decimal(7,2))
WHEN cr.ContasReceberJuros >= 0 THEN Cast((cr.ContasReceberValor * 0.01 / 30 * DiasAtraso)as Decimal(7,2))
ELSE cr.ContasReceberJuros END AS Juros
From TBContasReceber cr
Where ContasReceberStatus 'V'
GOSTEI 0
POSTAR