Gerar Parcelas com Dia Padrão em Vencimento
Bom dia Povo Abeçoado, estou precisando da ajuda de vocês.
No meu financeiro eu tenho um campo chamado dia padrão, caso o usuario queira escolher um dia padrão para gerar as parcelas, ex: vamos supor que um cliente queira suas parcelas para todo dia 10, ou todo dia 5 de cada mês.
Eu trabalho com o firebird.2.5 e estou querendo fazer com que minha procedure gere parcelas com as seguintes condições:
Se o vencimento for de 30 em 30 dias ele gere o vencimento de acordo com o dia padrão.
Eu tenho um storeprocedure que faz com que gere as parcelas de 30 em 30, de 7 em 7, isso de acordo com a condição de pagamento, mas eu queria adaptar essa parte do dia padrão.
Sei que para que posso extrar um dia uma data eu uso Extract(Day From current_date), mas eu preciso pergar esse dia e alterar somente o dia dos vencimentos.
Meu vencimento eu gero assim: :VENCIMENTO + CAST(SUBSTRING(:QtdeDias FROM :ContadorString FOR 3) AS INTEGER) /* Vencimento ele pega a quantidade de dias para somar (se é de 15 em 15, de 7 em 7, etc...) */
na minha tabela de condição de pagamento eu tenho os campos CPGTO_DIVISOR,CPGTO_PERIODO onde eu informo o numero pelo qual vou dividir e o periodo, ex:
DESCRICAO CPGTO_DIVISOR CPGTO_PERIODO
030/060/090 3 030/060/090
neste exemplo ele gera de 30 em 30 dias.
exemplo
01/01/2012 + 30 = 31/01/2012 = 30 = 29/02/2012 -> Eu preciso fazer com que essas datas sejam alteradas para o dia padrão, se o dia padrão fosse 01 de cada mes, então teria que ficar: 01/01/2012 / 01/02/2012 / 01/03/2012
create or alter procedure sp_contaspagar_lancamento (
ctpg_id type of column contaspagar.ctpg_id,
data_emissao type of column contaspagar.ctpg_id,
for_id type of column contaspagar.for_id,
cen_id type of column contaspagar.cen_id,
ctpg_nfe type of column contaspagar.ctpg_nfe,
ctpg_historico type of column contaspagar.ctpg_historico,
ctpg_num_doc type of column contaspagar.ctpg_num_doc,
fpgto_id_lanc type of column contaspagar.fpgto_id_lanc,
condicao_pagamento type of column contaspagar.cpgto_id,
tip_id type of column contaspagar.tip_id,
ctpg_qtde_parcela type of column contaspagar.ctpg_qtde_parcela,
ctpg_num_parcela type of column contaspagar.ctpg_num_parcela,
ctpg_dia_padrao type of column contaspagar.ctpg_dia_padrao,
ctpg_valor_parcela type of column contaspagar.ctpg_valor_parcela,
ctpg_valor_total type of column contaspagar.ctpg_valor_total,
data_vencimento type of column contaspagar.data_vencimento,
status type of column contaspagar.status,
usu_id type of column contaspagar.usu_id,
loj_id type of column contaspagar.loj_id,
excluido type of column contaspagar.excluido)
returns (
ok integer)
as
declare variable qtdedias varchar(60);
declare variable divisor integer;
declare variable contador integer = 1;
declare variable contadorstring integer = 1;
declare variable existe integer;
begin
/* Verificando se a forma de pagamento existe, se for maior que 0 é pq existe */
select count(*) from condicao_de_pagamento where CPGTO_ID = :condicao_pagamento
into :existe;
/* Se a a Condição de Pagamento existir relaiza o processo */
if (:existe > 0) then
begin
/* Recebendo as informações da Condição de Pagamento */
select
CPGTO_DIVISOR,
REPLACE(CPGTO_PERIODO, /,)
from
condicao_de_pagamento
where
CPGTO_ID = :condicao_pagamento AND
CPGTO_PERIODO IS NOT NULL
into :Divisor, :QtdeDias;
begin
/* Gerando as Parcelas */
while (Contador <= Divisor) do
begin
insert into contaspagar (
ctpg_id,
data_emissao,
for_id,
cen_id,
ctpg_nfe,
ctpg_historico,
ctpg_num_doc,
fpgto_id_lanc,
cpgto_id,
tip_id,
ctpg_qtde_parcela,
ctpg_num_parcela,
ctpg_dia_padrao,
ctpg_valor_parcela,
ctpg_valor_total,
data_vencimento,
status,
usu_id,
loj_id,
excluido)
values (
NEXT VALUE FOR GEN_CONTASPAGAR_ID,
:data_emissao,
:for_id,
:cen_id,
:ctpg_nfe,
:ctpg_historico,
:ctpg_num_doc || / || :Contador , /* Número do documento */
:fpgto_id_lanc,
:condicao_pagamento,
:tip_id,
:ctpg_qtde_parcela,
:Contador || / || :divisor, /* Número da parcela */
:ctpg_dia_padrao,
:ctpg_valor_total/:divisor, /* Valor da parcela */
:ctpg_valor_total,
:data_emissao + CAST(SUBSTRING(:QtdeDias FROM :ContadorString FOR 3) AS INTEGER), /* Vencimento ele pega a quantidade de dias para somar (se é de 15 em 15, de 7 em 7, etc...) */
0, /* Status Não Conciliado */
:usu_id,
:loj_id,
N);
Contador = Contador+1; /* Incrementa o Contador */
ContadorString = ContadorString+3; /* Incrementa o Contador da string */
end
end
ok = 1;
end
else
EXCEPTION MENSAGEM Não Existe essa Condição de Pagamento!;
end
No meu financeiro eu tenho um campo chamado dia padrão, caso o usuario queira escolher um dia padrão para gerar as parcelas, ex: vamos supor que um cliente queira suas parcelas para todo dia 10, ou todo dia 5 de cada mês.
Eu trabalho com o firebird.2.5 e estou querendo fazer com que minha procedure gere parcelas com as seguintes condições:
Se o vencimento for de 30 em 30 dias ele gere o vencimento de acordo com o dia padrão.
Eu tenho um storeprocedure que faz com que gere as parcelas de 30 em 30, de 7 em 7, isso de acordo com a condição de pagamento, mas eu queria adaptar essa parte do dia padrão.
Sei que para que posso extrar um dia uma data eu uso Extract(Day From current_date), mas eu preciso pergar esse dia e alterar somente o dia dos vencimentos.
Meu vencimento eu gero assim: :VENCIMENTO + CAST(SUBSTRING(:QtdeDias FROM :ContadorString FOR 3) AS INTEGER) /* Vencimento ele pega a quantidade de dias para somar (se é de 15 em 15, de 7 em 7, etc...) */
na minha tabela de condição de pagamento eu tenho os campos CPGTO_DIVISOR,CPGTO_PERIODO onde eu informo o numero pelo qual vou dividir e o periodo, ex:
DESCRICAO CPGTO_DIVISOR CPGTO_PERIODO
030/060/090 3 030/060/090
neste exemplo ele gera de 30 em 30 dias.
exemplo
01/01/2012 + 30 = 31/01/2012 = 30 = 29/02/2012 -> Eu preciso fazer com que essas datas sejam alteradas para o dia padrão, se o dia padrão fosse 01 de cada mes, então teria que ficar: 01/01/2012 / 01/02/2012 / 01/03/2012
create or alter procedure sp_contaspagar_lancamento (
ctpg_id type of column contaspagar.ctpg_id,
data_emissao type of column contaspagar.ctpg_id,
for_id type of column contaspagar.for_id,
cen_id type of column contaspagar.cen_id,
ctpg_nfe type of column contaspagar.ctpg_nfe,
ctpg_historico type of column contaspagar.ctpg_historico,
ctpg_num_doc type of column contaspagar.ctpg_num_doc,
fpgto_id_lanc type of column contaspagar.fpgto_id_lanc,
condicao_pagamento type of column contaspagar.cpgto_id,
tip_id type of column contaspagar.tip_id,
ctpg_qtde_parcela type of column contaspagar.ctpg_qtde_parcela,
ctpg_num_parcela type of column contaspagar.ctpg_num_parcela,
ctpg_dia_padrao type of column contaspagar.ctpg_dia_padrao,
ctpg_valor_parcela type of column contaspagar.ctpg_valor_parcela,
ctpg_valor_total type of column contaspagar.ctpg_valor_total,
data_vencimento type of column contaspagar.data_vencimento,
status type of column contaspagar.status,
usu_id type of column contaspagar.usu_id,
loj_id type of column contaspagar.loj_id,
excluido type of column contaspagar.excluido)
returns (
ok integer)
as
declare variable qtdedias varchar(60);
declare variable divisor integer;
declare variable contador integer = 1;
declare variable contadorstring integer = 1;
declare variable existe integer;
begin
/* Verificando se a forma de pagamento existe, se for maior que 0 é pq existe */
select count(*) from condicao_de_pagamento where CPGTO_ID = :condicao_pagamento
into :existe;
/* Se a a Condição de Pagamento existir relaiza o processo */
if (:existe > 0) then
begin
/* Recebendo as informações da Condição de Pagamento */
select
CPGTO_DIVISOR,
REPLACE(CPGTO_PERIODO, /,)
from
condicao_de_pagamento
where
CPGTO_ID = :condicao_pagamento AND
CPGTO_PERIODO IS NOT NULL
into :Divisor, :QtdeDias;
begin
/* Gerando as Parcelas */
while (Contador <= Divisor) do
begin
insert into contaspagar (
ctpg_id,
data_emissao,
for_id,
cen_id,
ctpg_nfe,
ctpg_historico,
ctpg_num_doc,
fpgto_id_lanc,
cpgto_id,
tip_id,
ctpg_qtde_parcela,
ctpg_num_parcela,
ctpg_dia_padrao,
ctpg_valor_parcela,
ctpg_valor_total,
data_vencimento,
status,
usu_id,
loj_id,
excluido)
values (
NEXT VALUE FOR GEN_CONTASPAGAR_ID,
:data_emissao,
:for_id,
:cen_id,
:ctpg_nfe,
:ctpg_historico,
:ctpg_num_doc || / || :Contador , /* Número do documento */
:fpgto_id_lanc,
:condicao_pagamento,
:tip_id,
:ctpg_qtde_parcela,
:Contador || / || :divisor, /* Número da parcela */
:ctpg_dia_padrao,
:ctpg_valor_total/:divisor, /* Valor da parcela */
:ctpg_valor_total,
:data_emissao + CAST(SUBSTRING(:QtdeDias FROM :ContadorString FOR 3) AS INTEGER), /* Vencimento ele pega a quantidade de dias para somar (se é de 15 em 15, de 7 em 7, etc...) */
0, /* Status Não Conciliado */
:usu_id,
:loj_id,
N);
Contador = Contador+1; /* Incrementa o Contador */
ContadorString = ContadorString+3; /* Incrementa o Contador da string */
end
end
ok = 1;
end
else
EXCEPTION MENSAGEM Não Existe essa Condição de Pagamento!;
end
Sidney Abreu
Curtidas 0
Respostas
Antonio Jesus
05/01/2012
Olá, boa tarde!
TEnho uma rotina que faço isso no meu sistema, de uma olha e veja se te ajuda.
100+
ANT.CARLOS/SP
========================================================================================
procedure Carteira.Calc_Parcelas_Vmdia();
Var K,Qtdparc: Integer;
k_vlparc, k_totparc: Currency;
k_resto : Real;
Nparc : Integer;
MesAno, Descr : String;
Dia,Mes,Ano : Word;
Vcto_Normal : Boolean;
k_dtvenc : TdateTime;
begin
QtdParc := Sql_PesqCond.FieldByName(Qtdparc).AsInteger;
If Sql_PesqCond.FieldByName(Condpgto).AsInteger <= 2 Then
QtdParc := QtdParc - 1;
k_dtvenc := Dtvenda;
k_vlparc := StrToCurr(FormatCurr(#########.00,(Vltotal/Qtdparc)));
k_totparc := (k_vlparc * Qtdparc);
k_resto := 0;
Nparc := 0;
IF k_totparc > Vltotal Then
k_resto := ((((k_totparc*100)-(Vltotal*100))/100)* -1)
Else
k_resto := (((Vltotal*100) - (k_totparc*100))/100);
IF k_resto > 0 Then
k_resto := StrTOCurr(FormatCurr(##0.000,k_resto));
Sql_PesqItcond.First;
DecodeDate(Dtvenda,Ano,Mes,Dia);
WHILE NOT Sql_PesqItcond.EOF DO Begin
Mes := Mes + 1;
If Mes > 12 Then Begin
Mes := 1;
Ano := Ano+1;
End;
//--------------------------------------------------//
//...Valida o Vencimento //
//--------------------------------------------------//
k_dtvenc := Valida_Vencimento(Dia,Mes,Ano);
Inc(Nparc);
Cds_Carteira.Append;
Cds_Carteira.FieldByName(Numseq).AsInteger := Nparc;
Cds_Carteira.FieldByName(Nparc).AsString := FormatFloat(00,Nparc)+/+FormatFloat(00,QtdParc);
Cds_Carteira.FieldByName(Dtvcto).AsDateTime := k_dtvenc;
Cds_Carteira.FieldByName(Numdoc).AsString := VD-+IntToStr(Codvenda);
Cds_Carteira.FieldByName(Vlparc).AsCurrency := k_vlparc+k_resto;
k_resto := 0;
Cds_Carteira.Post;
Sql_PesqItcond.Next;
End;
//-------------------------------------------------------//
//.....Acessa Rotina para Acertar dias dos Vencimentos //
// No Mesmo Dia //
//-------------------------------------------------------//
Calc_Vcmto_MesmoDia(Cds_Carteira,0);
Cds_Carteira.First;
end;
procedure Calc_Vcmto_MesmoDia(Var Cds_Parcela: TClientDataSet;Qtcarencia:Integer);
Var Contador : Integer;
Dtvcto : TdateTime;
Anon, Mesn,Dian, Dia_fixo, Dia, Mes, Ano : Word;
Mesano : String;
Begin
Try
Cds_Parcela.IndexFieldNames := NPARC;
Cds_Parcela.First;
DecodeDate(Cds_Parcela.FieldByName(Dtvcto).AsDateTime,Ano,Mes,Dia);
Dia_Fixo := Dia;
Mesn := Mes;
Anon := Ano;
While not Cds_Parcela.eof do Begin
Dian := Dia_fixo;
If (Mesn = 02) and (Dian > 28) Then Begin //...Fevereiro
Mesano := FormatFloat(00,Mesn)+/+FormatFloat(0000,Anon);
Dian := Ultimo_dia_mes(Mesano);
End Else if (Dian = 31) and ((Mesn = 01) or (Mesn = 03) or (Mesn = 05) or (Mesn = 07) or (Mesn = 08) or (Mesn = 10) or (Mesn = 12)) Then Begin
Dian := 30;
End Else if (Dian >= 30) and ((Mesn = 04) or (Mesn = 06) or (Mesn = 08) or (Mesn = 09) or (Mesn = 11)) Then Begin
Dian := 30;
End;
Dtvcto := EncodeDate(Anon,Mesn,Dian);
Cds_Parcela.Edit;
Cds_Parcela.FieldByName(DTVCTO).AsDateTime := Dtvcto;
Cds_Parcela.Post;
Mesn := Mesn + 1;
If Mesn > 12 Then Begin
Mesn := 1;
Anon := Anon + 1;
End;
Cds_Parcela.Next;
End;
Finally
Cds_Parcela.IndexFieldNames := Dtvcto;
Cds_Parcela.First;
End;
End;
========================================================================================
TEnho uma rotina que faço isso no meu sistema, de uma olha e veja se te ajuda.
100+
ANT.CARLOS/SP
========================================================================================
procedure Carteira.Calc_Parcelas_Vmdia();
Var K,Qtdparc: Integer;
k_vlparc, k_totparc: Currency;
k_resto : Real;
Nparc : Integer;
MesAno, Descr : String;
Dia,Mes,Ano : Word;
Vcto_Normal : Boolean;
k_dtvenc : TdateTime;
begin
QtdParc := Sql_PesqCond.FieldByName(Qtdparc).AsInteger;
If Sql_PesqCond.FieldByName(Condpgto).AsInteger <= 2 Then
QtdParc := QtdParc - 1;
k_dtvenc := Dtvenda;
k_vlparc := StrToCurr(FormatCurr(#########.00,(Vltotal/Qtdparc)));
k_totparc := (k_vlparc * Qtdparc);
k_resto := 0;
Nparc := 0;
IF k_totparc > Vltotal Then
k_resto := ((((k_totparc*100)-(Vltotal*100))/100)* -1)
Else
k_resto := (((Vltotal*100) - (k_totparc*100))/100);
IF k_resto > 0 Then
k_resto := StrTOCurr(FormatCurr(##0.000,k_resto));
Sql_PesqItcond.First;
DecodeDate(Dtvenda,Ano,Mes,Dia);
WHILE NOT Sql_PesqItcond.EOF DO Begin
Mes := Mes + 1;
If Mes > 12 Then Begin
Mes := 1;
Ano := Ano+1;
End;
//--------------------------------------------------//
//...Valida o Vencimento //
//--------------------------------------------------//
k_dtvenc := Valida_Vencimento(Dia,Mes,Ano);
Inc(Nparc);
Cds_Carteira.Append;
Cds_Carteira.FieldByName(Numseq).AsInteger := Nparc;
Cds_Carteira.FieldByName(Nparc).AsString := FormatFloat(00,Nparc)+/+FormatFloat(00,QtdParc);
Cds_Carteira.FieldByName(Dtvcto).AsDateTime := k_dtvenc;
Cds_Carteira.FieldByName(Numdoc).AsString := VD-+IntToStr(Codvenda);
Cds_Carteira.FieldByName(Vlparc).AsCurrency := k_vlparc+k_resto;
k_resto := 0;
Cds_Carteira.Post;
Sql_PesqItcond.Next;
End;
//-------------------------------------------------------//
//.....Acessa Rotina para Acertar dias dos Vencimentos //
// No Mesmo Dia //
//-------------------------------------------------------//
Calc_Vcmto_MesmoDia(Cds_Carteira,0);
Cds_Carteira.First;
end;
procedure Calc_Vcmto_MesmoDia(Var Cds_Parcela: TClientDataSet;Qtcarencia:Integer);
Var Contador : Integer;
Dtvcto : TdateTime;
Anon, Mesn,Dian, Dia_fixo, Dia, Mes, Ano : Word;
Mesano : String;
Begin
Try
Cds_Parcela.IndexFieldNames := NPARC;
Cds_Parcela.First;
DecodeDate(Cds_Parcela.FieldByName(Dtvcto).AsDateTime,Ano,Mes,Dia);
Dia_Fixo := Dia;
Mesn := Mes;
Anon := Ano;
While not Cds_Parcela.eof do Begin
Dian := Dia_fixo;
If (Mesn = 02) and (Dian > 28) Then Begin //...Fevereiro
Mesano := FormatFloat(00,Mesn)+/+FormatFloat(0000,Anon);
Dian := Ultimo_dia_mes(Mesano);
End Else if (Dian = 31) and ((Mesn = 01) or (Mesn = 03) or (Mesn = 05) or (Mesn = 07) or (Mesn = 08) or (Mesn = 10) or (Mesn = 12)) Then Begin
Dian := 30;
End Else if (Dian >= 30) and ((Mesn = 04) or (Mesn = 06) or (Mesn = 08) or (Mesn = 09) or (Mesn = 11)) Then Begin
Dian := 30;
End;
Dtvcto := EncodeDate(Anon,Mesn,Dian);
Cds_Parcela.Edit;
Cds_Parcela.FieldByName(DTVCTO).AsDateTime := Dtvcto;
Cds_Parcela.Post;
Mesn := Mesn + 1;
If Mesn > 12 Then Begin
Mesn := 1;
Anon := Anon + 1;
End;
Cds_Parcela.Next;
End;
Finally
Cds_Parcela.IndexFieldNames := Dtvcto;
Cds_Parcela.First;
End;
End;
========================================================================================
GOSTEI 0
Flavia Santos
05/01/2012
No Firebird há a função DATEADD(), com ela você pode adicionar anos, meses, semanas, dias, horas, minutos, segundos ou até mesmo milésimo de segundos a uma data dos tipos DATE, TIME, ou TIMESTAMP. Alguns exemplos de utilização da função:
dateadd (30 day to current_date)
dateadd (-6 hour to current_time)
dateadd (month, 9, DateOfConception)
dateadd (-38 week to DateOfBirth)
dateadd (minute, 90, time now)
dateadd (? year to date 11-Sep-1973)
Você pode pegar o dia padrão, calcular o primeiro vencimento e depois vai apenas utilizando esta função para achar os demais vencimentos.
Talvez isso te ajude,
Flw.
dateadd (30 day to current_date)
dateadd (-6 hour to current_time)
dateadd (month, 9, DateOfConception)
dateadd (-38 week to DateOfBirth)
dateadd (minute, 90, time now)
dateadd (? year to date 11-Sep-1973)
Você pode pegar o dia padrão, calcular o primeiro vencimento e depois vai apenas utilizando esta função para achar os demais vencimentos.
Talvez isso te ajude,
Flw.
GOSTEI 0