Fórum Problema com data me tirando do sério #372182

12/07/2009

0

Possuo um sistema q dentre outras funções gera parcelas de pagamento, sendo permitido ao operador modificar essa data caso não seja uma data ideal para o cliente naquele mês (é feita uma ligação antes pra confirmar), a operadora escolhe a nova data em um DateTimePeacker, no closeup, tenho a seguinte rotina:


procedure TFrm_Recibos_Impressao.Cbo_DataCloseUp(Sender: TObject);
var Q_Qr:TSqlquery;
    dt: TDate;
    diautil,diadomes,diadasemana:boolean;
begin
   diautil := False;
   diadomes := False;
   diadasemana := false;

    dt:= cbo_data.Date;
    diautil := Data_util(datetostr(dt)) = ´N´;
    diadomes := DayOfTheMonth(dt) = 1;
    diadasemana := DayOfWeek(dt) = 1;
    if (diautil) and (diadomes) then
     dt := IncDay(dt,1)
    else
    if diautil then
     dt := IncDay(dt,-1)
    else
    if (diadomes) and (diadasemana) then
     dt := IncDay(dt,1)
    else
    If diadasemana then
     dt := IncDay(dt,-1)
    else
     dt := Cbo_Data.Date;

    if Q_Doacoes_Impressao.RecordCount > 0 then
     begin
      Q_Qr := TSQLQuery.Create(nil);
      Q_Qr.SQLConnection := dm.Conexao;
      Q_Qr.SQL.Add(´UPDATE TAB_DOACOES SET DOC_DATA_OPERACAO = :data WHERE DOC_ID =´+Q_Doacoes_ImpressaoDOC_ID.AsString);
      Q_Qr.Params.ParamByName(´data´).AsDate := dt;
      Q_Qr.ExecSQL;
      Q_Qr.Free;
     end;
end;


e a função Data_util, q verifica se é uma data válida e faz uma consulta a uma tabela de feriados pra saber se é feriados ou não.

function TFrm_Recibos_Impressao.Data_util(data: string): string;
begin
  If Not dm.F_Data_Valida(data) Then
  Begin
    Exit;
  End;
    Try
      dm.dsQ_Query2.Close;
      dm.dsQ_Query2.Params.ParamByName(´DATA´).AsDate := strtodate(data);
      dm.dsQ_Query2.Open;
    Except
      MessageDlg(´Aconteceu um erro no momento da obtenção dos dados! Contacte o administrador do sistema!´,mtError,[mbOK],0);
      Exit;
    End;

    if dm.dsQ_Query2.RecordCount = 0 then
     Result := ´S´
    else
     Result := ´N´;

end;


e o problema é o seguinte:

quando se entra no sistema, tudo funciona perfeitamente, escolhe uma data, se for feriado ele decrementa um dia, se for domingo, decrementa um dia, se for um dia normal, fica na data escolhida; só que no decorrer da operação do sistema a coisa começa a desandar, toda data q é escolhida, independente de ser válida ou não, o sistema decrementa um dia, ai tem q fechar o sistema e abrí-lo quando tudo funciona normal de novo e assim fica o dia todo, deu problema, fecha e abre.

Será q estou esquecendo de retirar algo da memória?[/code]


Fajo

Fajo

Responder

Posts

13/07/2009

Emerson Nascimento

acho é preciso fazer mais algumas análises:
- não há pagamento no dia 1o. do mês???
- se a data escolhida for uma segunda-feira e essa segunda feira for feriado, o sistema deixará como data de pagamento o domingo. é isso mesmo?
- o correto, ao cair num domingo ou feriado, não seria INcrementar ao invés de decrementar?
- e quanto ao sábado???? se o dia escolhido for domingo o sistema muda pra sábado???


Responder

Gostei + 0

13/07/2009

Emerson Nascimento

eu incrementaria a data, como é o comum no caso de parcelamentos:
procedure TFrm_Recibos_Impressao.cbo_dataCloseUp(Sender: TObject);
var
  Q_Qr:TSqlquery;
  dt: TDate;
  diautil, diaprimeiro, domingo: boolean;
begin
  dt := cbo_data.Date;

  // enquanto a data for um fim-de-semana ou feriado,
  // joga a data 1 dia "pra frente"...
  while not Data_util(dt) do
    dt := IncDay(dt, 1);

  if Q_Doacoes_Impressao.Active and not Q_Doacoes_Impressao.IsEmpty then
  begin
    Q_Qr := TSQLQuery.Create(nil);
    Q_Qr.SQLConnection := dm.Conexao;
    Q_Qr.SQL.Add(´UPDATE TAB_DOACOES SET DOC_DATA_OPERACAO = :data WHERE DOC_ID =´+Q_Doacoes_ImpressaoDOC_ID.AsString);
    Q_Qr.Params.ParamByName(´data´).AsDate := dt;
    Q_Qr.ExecSQL;
    Q_Qr.Free;
  end;
end;


e faria minha função de avaliação de ´dia útil´ da seguinte forma:
function TFrm_Recibos_Impressao.Data_util(datainformada: TDate): boolean;
begin
  Result := not (DayOfWeek(datainformada) in [1, 7]); // sábado ou domingo

  // se não é um fim de semana, verifico se é um feriado
  if Result then
  begin
    try
      dm.dsQ_Query2.Close;
      dm.dsQ_Query2.Params.ParamByName(´DATA´).AsDate := datainformada;
      dm.dsQ_Query2.Open;
    except
      MessageDlg(´Aconteceu um erro no momento da obtenção dos dados! Contacte o administrador do sistema!´,mtError,[mbOK],0);
      Exit;
    end;

    // se o resultset estiver vazio, é uma data válida
    Result := dm.dsQ_Query2.IsEmpty;
  end;
end;


nota 1: não utilize Recordcount, a menos que você queira saber exatamente qual foi o número de registros retornados, o que não é o caso nas suas rotinas.
nota 2: só pra constar, todas as suas datas vinham decrementadas em 1 devido ao código
 if diautil then
     dt := IncDay(dt,-1)



Responder

Gostei + 0

13/07/2009

Fajo

Vamos lá emerson,

- não há pagamento no dia 1o. do mês???

há sim:

só q se for no dia 1º, ele incrementa para o dia 2 e não para o mês anterior.

- se a data escolhida for uma segunda-feira e essa segunda feira for feriado, o sistema deixará como data de pagamento o domingo. é isso mesmo?

na verdade não, se cair num domingo tem q ser decrementada pra sábado.

realmente já tinha percebido essa falha, obrigado.

- o correto, ao cair num domingo ou feriado, não seria INcrementar ao invés de decrementar?

.
.
diadasemana := DayOfWeek(dt) = 1; 
.
.
If diadasemana then
     dt := IncDay(dt,-1) 



não utilize Recordcount, a menos que você queira saber exatamente qual foi o número de registros retornados, o que não é o caso nas suas rotinas.

obrigado, pela sugestão, irei implementá-la.

só pra constar, todas as suas datas vinham decrementadas em 1 devido ao código


mas somente se a função diautil retornar true, senão, vai pro próximo if.

agora, o q me deixa perdido é exatamento pq funciona bem por um perido de tempo e depois, começa a decrementar pra toda data.[/code]


Responder

Gostei + 0

14/07/2009

Emerson Nascimento

Vamos lá emerson, [quote:551123a5ad=´emerson.en´]- não há pagamento no dia 1o. do mês???

há sim:
só q se for no dia 1º, ele incrementa para o dia 2 e não para o mês anterior.[/quote:551123a5ad]
ENTÃO NÃO HÁ PAGAMENTO NO DIA 1o.

agora, o q me deixa perdido é exatamento pq funciona bem por um perido de tempo e depois, começa a decrementar pra toda data.


um dos fatores é justamente pelo código mostrado:
if diautil then
     dt := IncDay(dt,-1) 


vejamos seu código (troquei o nome de algumas variáveis pra ficar mais amigável):
procedure TFrm_Recibos_Impressao.Cbo_DataCloseUp(Sender: TObject);
var Q_Qr:TSqlquery;
    dt: TDate;
    diautil,diaprimeiro,domingo:boolean;
begin
   diautil := False;
   diaprimeiro := False;
   domingo := false;

    dt:= cbo_data.Date;
    diautil := Data_util(datetostr(dt)) = ´N´;
    diaprimeiro := DayOfTheMonth(dt) = 1;
    domingo := DayOfWeek(dt) = 1;
    if (diautil) and (diaprimeiro) then
     dt := IncDay(dt,1)
    else
    if diautil then
     dt := IncDay(dt,-1)
    else
    if (diaprimeiro) and (domingo) then
     dt := IncDay(dt,1)
    else
    If domingo then
     dt := IncDay(dt,-1)
    else
     dt := Cbo_Data.Date;

    if Q_Doacoes_Impressao.RecordCount > 0 then
     begin
      Q_Qr := TSQLQuery.Create(nil);
      Q_Qr.SQLConnection := dm.Conexao;
      Q_Qr.SQL.Add(´UPDATE TAB_DOACOES SET DOC_DATA_OPERACAO = :data WHERE DOC_ID =´+Q_Doacoes_ImpressaoDOC_ID.AsString);
      Q_Qr.Params.ParamByName(´data´).AsDate := dt;
      Q_Qr.ExecSQL;
      Q_Qr.Free;
     end;
end;


tomemos o calendário abaixo como exemplo:
 D  S  T  Q  Q  S  S
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
imagine que não há feriado no mês apresentado.

eis o trecho que controla a mudança do dia
    if (diautil) and (diaprimeiro) then
     dt := IncDay(dt,1)
    else
    if diautil then
     dt := IncDay(dt,-1)
    else
    if (diaprimeiro) and (domingo) then
     dt := IncDay(dt,1)
    else
    If domingo then
     dt := IncDay(dt,-1)
    else
     dt := Cbo_Data.Date;


- se for escolhido dia 1o, seu código mudará para dia 2, porque é um dia útil e é dia primeiro.
    if (diautil) and (diaprimeiro) then
     dt := IncDay(dt,1)

- se for escolhido dia 6, seu código mudará para dia 5, pois é um domingo
    If domingo then
     dt := IncDay(dt,-1)

- agora, se for escolhido qualquer outro dia que não seja domingo nem seja dia 1o, seu código irá mudar para o dia anterior, devido ao trecho
    if diautil then
     dt := IncDay(dt,-1)

porque o if segue o fluxo, não vai chegar no else porque a segunda condição será válida antes de chegar lá. ao que parece a data só permanecerá aquela escolhida se for selecionado um sábado que não seja dia 1o.

Aliás, o que você considera como dia útil? Para essa sua necessidade, sábado é um dia útil?


Responder

Gostei + 0

14/07/2009

Fajo

Mas emerson, o código:

    if dm.dsQ_Query2.RecordCount = 0 then
     Result := ´S´
    else
     Result := ´N´;


da função Date_util diz q, se retornar ´S´, a variável diautil recebera False, onde dessa forma ele não deveria cair entrar no:
if diautil then
     dt := IncDay(dt,-1) 


e sim, continuar o fluxo até chegar no
else
     dt := Cbo_Data.Date;


o q vc acha?


Responder

Gostei + 0

14/07/2009

Emerson Nascimento

não dá pra dizer com certeza, porque algumas coisas estão ocultas...

o que faz a função [i:7408b54057]F_Data_Valida[/i:7408b54057]?

qual a instrução da [i:7408b54057]dm.dsQ_Query2[/i:7408b54057]?

e, pra te falar a verdade eu nunca vi uma avaliação dessas, em que se retrocede o dia de vencimento.

e você não me respondeu como é considerado o sábado. é um dia útil?


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar