Problem w zależnościach dat w procedurze

0

Witam kolegów.
Mózg mi wysechł od myślenia i kombinowania jak to zrobić. Mianowicie chodzi o stworzenie procedury sprawdzającej poprawność zależności pomiędzy datami sprzedaży towaru a wystawienia faktury zgodnie z przepisami. Stworzyłem coś takiego i klops. Działa jak chce. Wiem, że nie ma warunku sprawdzenia ostatniego wpisu z rejestru sprzedaży, ale mimo tego żyje to własnym życiem. Ktoś pomoże?
Treść procedury

procedure TForm2.SprawdzDatySprzedazyIFaktury(Sender : TObject);
var
  MinDataFaktury, MaxDataFaktury: TDate;
  MinDataSprzedazy, MaxDataSprzedazy: TDate;
begin
  // Obliczenia zależności daty faktury względem daty sprzedaży
  MinDataFaktury := DateTimePicker1.Date - 60;  // Faktura maksymalnie 60 dni przed sprzedażą
  MaxDataFaktury := EndOfTheMonth(DateTimePicker1.Date) + 15;  // Faktura maksymalnie do 15. dnia następnego miesiąca

  // Obliczenia zależności daty sprzedaży względem daty faktury
  MinDataSprzedazy := DateTimePicker2.Date;  // Sprzedaż najwcześniej w dniu wystawienia faktury
  MaxDataSprzedazy := DateTimePicker2.Date + 60;  // Sprzedaż maksymalnie 60 dni po wystawieniu faktury

  // Sprawdzanie, czy DataFaktury mieści się w zakresie określonym przez datę sprzedaży
  if (DateTimePicker1.Date < MinDataFaktury) then
  begin
    ShowMessage('Data wystawienia faktury jest za wczesna. Możliwa data faktury to minimum ' +
      DateToStr(MinDataFaktury) + ' (do 60 dni przed sprzedażą).');
      DateTimePicker2.Date := MinDataFaktury;
    Exit;
  end
  else if (DateTimePicker2.Date > MaxDataFaktury) then
  begin
    ShowMessage('Data wystawienia faktury jest za późna. Maksymalna data faktury to ' +
      DateToStr(MaxDataFaktury) + ' (do 15. dnia następnego miesiąca po sprzedaży).');
      DateTimePicker2.Date := MaxDataFaktury;
    Exit;
  end;

  // Sprawdzanie, czy DataSprzedazy mieści się w zakresie określonym przez datę faktury
  if (DateTimePicker1.Date < MinDataSprzedazy) then
  begin
    ShowMessage('Data sprzedaży jest za wczesna. Musi być co najmniej równa dacie faktury: ' +
      DateToStr(MinDataSprzedazy) + '.');
      DateTimePicker1.Date := MinDataSprzedazy;
    Exit;
  end
  else if (DateTimePicker1.Date > MaxDataSprzedazy) then
  begin
    ShowMessage('Data sprzedaży jest za późna. Możliwa data sprzedaży to maksimum ' +
      DateToStr(MaxDataSprzedazy) + ' (do 60 dni po dacie faktury).');
      DateTimePicker1.Date := MaxDataSprzedazy;
    Exit;
  end;

Przepraszam, za bałagan w kodzie o wszechobecne okna z wiadomościami, ale już sam nie wiem jak to ugryźć.
Z góry dzięki za rozwiązania.

1

Jeśli dobrze rozumiem to masz dwie daty, datę faktury (InvoiceDate) oraz datę sprzedaży (Transaction Date) .
Napisz sobie w punktach jakie warunki muszą być spełnione. Łatwiej będzie ogarnąć problem
Np.

  1. InvoiceDate>=TransactionDate
  2. ....

Napisał bym funkcję, np. ..

Type TresultRec=record
  errorCode:integer;
  errorMessage:string;
  
end;

function validateDates(aInvoiceDate,aTransactionDate:Tdate): TresultRec;
begin 
  result.errorcode:=0;
  result.errorMessage:='';
  if not (InvoiceDate>=TransactionDate) then 
  begin 
      result.errorcode:=1;
      result.errorMessage:='Data wystawienia faktury jest za wczesna.';
      exit
  end;
  //// kolejne warunki
  ////
  ////
end;

Bałagan w kodzie, w tym zupełnie niepotrzebne else if, sprawia że trudno Ci się w tym połapać

procedure TForm2.SprawdzDatySprzedazyIFaktury(Sender : TObject);
var
  MinDataFaktury, MaxDataFaktury: TDate;
  MinDataSprzedazy, MaxDataSprzedazy: TDate;
begin
  // Obliczenia zależności daty faktury względem daty sprzedaży
  MinDataFaktury := DateTimePicker1.Date - 60;  // Faktura maksymalnie 60 dni przed sprzedażą
  MaxDataFaktury := EndOfTheMonth(DateTimePicker1.Date) + 15;  // Faktura maksymalnie do 15. dnia następnego miesiąca

  // Obliczenia zależności daty sprzedaży względem daty faktury
  MinDataSprzedazy := DateTimePicker2.Date;  // Sprzedaż najwcześniej w dniu wystawienia faktury
  MaxDataSprzedazy := DateTimePicker2.Date + 60;  // Sprzedaż maksymalnie 60 dni po wystawieniu faktury

  // Sprawdzanie, czy DataFaktury mieści się w zakresie określonym przez datę sprzedaży
  if (DateTimePicker1.Date < MinDataFaktury) then
  begin
    ShowMessage('Data wystawienia faktury jest za wczesna. Możliwa data faktury to minimum ' +
      DateToStr(MinDataFaktury) + ' (do 60 dni przed sprzedażą).');
      DateTimePicker2.Date := MinDataFaktury;
    Exit;
  end;

  if (DateTimePicker2.Date > MaxDataFaktury) then
  begin
    ShowMessage('Data wystawienia faktury jest za późna. Maksymalna data faktury to ' +
      DateToStr(MaxDataFaktury) + ' (do 15. dnia następnego miesiąca po sprzedaży).');
      DateTimePicker2.Date := MaxDataFaktury;
    Exit;
  end;

  // Sprawdzanie, czy DataSprzedazy mieści się w zakresie określonym przez datę faktury
  if (DateTimePicker1.Date < MinDataSprzedazy) then
  begin
    ShowMessage('Data sprzedaży jest za wczesna. Musi być co najmniej równa dacie faktury: ' +
      DateToStr(MinDataSprzedazy) + '.');
      DateTimePicker1.Date := MinDataSprzedazy;
    Exit;
  end;

  if (DateTimePicker1.Date > MaxDataSprzedazy) then
  begin
    ShowMessage('Data sprzedaży jest za późna. Możliwa data sprzedaży to maksimum ' +
      DateToStr(MaxDataSprzedazy) + ' (do 60 dni po dacie faktury).');
      DateTimePicker1.Date := MaxDataSprzedazy;
    Exit;
  end;
end;
0

Daty mają miedzy sobą określoną przepisami zależność. W skrócie data wystawienia faktury może nastąpić wcześniej niż 60 dni przed sprzedaniem/dostawą towaru i najpóźniej 15 dnia następnego miesiąca po miesiącu w którym nastąpiła sprzedaż i jakoś nie idzie mi zbudowanie tych wszystkich warunków. Niestety problem leży w tym również, że oba pola dat są edytowalne i w obu przypadkach należy te warunki posprawdzać. Stąd mam problem.

1

tu chyba chciałeś sprawdzić DateTimePicker2 bo wszędzie indziej przypisujesz wartość do sprawdzanego pola poza tym przypadkiem

 if (DateTimePicker1.Date < MinDataFaktury) then
  begin
    ShowMessage('Data wystawienia faktury jest za wczesna. Możliwa data faktury to minimum ' +
      DateToStr(MinDataFaktury) + ' (do 60 dni przed sprzedażą).');
      DateTimePicker2.Date := MinDataFaktury;
    Exit;
  end

w dodatku skoro przypisujesz

MinDataFaktury := DateTimePicker1.Date - 60

to warunek

if (DateTimePicker1.Date < MinDataFaktury) then

nigdy nie będzie prawdziwy.

Poza tym pozbądź się else z kodu, nie potrzebujesz go jeśli wychodzisz wcześnie wszędzie. W ogóle else nigdzie praktycznie nigdy nie potrzebujesz, jak potrzebuejsz to wydziel kod do osobnej metody i wyjdź wcześnie. Zmniejszaj skomplikowanie procedury bo w pewnym momencie wychodzi poza pojemność cache'u ludzkiego mózgu.

2

Daty mają miedzy sobą określoną przepisami zależność. W skrócie data wystawienia faktury może nastąpić wcześniej niż 60 dni przed sprzedaniem/dostawą towaru i najpóźniej 15 dnia następnego miesiąca po miesiącu w którym nastąpiła sprzedaż i jakoś nie idzie mi zbudowanie tych wszystkich warunków. Niestety problem leży w tym również, że oba pola dat są edytowalne i w obu przypadkach należy te warunki posprawdzać. Stąd mam problem.

var res:TresultRec;

res:=validateDates(DateTimePicker1.date,DateTimePicker2.date);
if res.errorcode<>0 then 
  showmessage(res.errorMesage);

Wszystkie wymagane zależności pomiędzy datami sprawdzasz w funkcji validateDates

Ps. zamiast DateTimePicker1 i DateTimePicker2 nadaj kontrolkom mówiące coś nazwy.

2

Wydaje mi się, że lepiej posłużyć się wyjątkami np. coś takiego:

type
  EValidateDateException = class(Exception)
    ErrorCode: Integer; // 1 - InvoiceDate, 2 - TransactionDate  
    ValidDate: TDate; // Poprawna data
  end;

  TForm1 = class(TForm)
    DTPickerInvoiceDate: TDateTimePicker;
    DTPickerTransactionDate: TDateTimePicker;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    
    procedure ValidateDates(AInvoiceDate, ATransactionDate: TDate);
    procedure DoValidateException(AMessageFrmt: string; AValidDate: TDate; AErrorCode: Integer = 0);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation


{$R *.dfm}

uses System.DateUtils;

procedure TForm1.ValidateDates(AInvoiceDate, ATransactionDate: TDate);
var
  MinInvoiceDate, MaxInvoiceDate: TDate;
  MinTransactionDate, MaxTransactionDate: TDate;
begin
  // Obliczenia zależności daty faktury względem daty sprzedaży
  MinInvoiceDate:= ATransactionDate - 60;  // Faktura maksymalnie 60 dni przed sprzedażą
  MaxInvoiceDate:= EndOfTheMonth(ATransactionDate) + 15;  // Faktura maksymalnie do 15. dnia następnego miesiąca
  // Obliczenia zależności daty sprzedaży względem daty faktury
  MinTransactionDate:= AInvoiceDate;  // Sprzedaż najwcześniej w dniu wystawienia faktury
  MaxTransactionDate:= AInvoiceDate + 60;  // Sprzedaż maksymalnie 60 dni po wystawieniu faktury
  if (AInvoiceDate < MinInvoiceDate) then
    DoValidateException('Data wystawienia faktury jest za wczesna. Możliwa data faktury to minimum: %s (do 60 dni przed sprzedażą).', MinInvoiceDate, 1);
  if (AInvoiceDate > MaxInvoiceDate) then
    DoValidateException('Data wystawienia faktury jest za późna. Maksymalna data faktury to: %s (do 15-tego dnia następnego miesiąca po sprzedaży).', MaxInvoiceDate, 1);
  if (ATransactionDate < MinTransactionDate) then
    DoValidateException('Data sprzedaży jest za wczesna. Musi być co najmniej równa dacie faktury: %s.', MinTransactionDate, 2);
  if (ATransactionDate > MaxTransactionDate) then
    DoValidateException('Data sprzedaży jest za późna. Możliwa data sprzedaży to maksimum: %s (do 60 dni po dacie faktury).', MaxTransactionDate, 2);
end;

procedure TForm1.DoValidateException(AMessageFrmt: string; AValidDate: TDate; AErrorCode: Integer = 0);
var
  Exception: EValidateDateException;
begin
  Exception:= EValidateDateException.CreateFmt(AMessageFrmt, [DateToStr(AValidDate)]);
  Exception.ValidDate:= AValidDate; 
  Exception.ErrorCode:= AErrorCode;
  raise Exception;
end;

procedure TForm1.Button1Click(Sender: TObject); //przykład uzycia
begin
  try
    ValidateDates(DTPickerInvoiceDate.Date, DTPickerTransactionDate.Date);

    //jest OK tu coś dalej...
  except
    on E: EValidateDateException do //zdefiniowany wyjątek w przypadku nieprawidłowej daty
    begin
      Application.MessageBox(PWideChar(E.Message), PWideChar(Application.Title + ' - Wybrano nieprawidłową datę'), MB_ICONERROR);
      if E.ErrorCode = 1 then
        DTPickerInvoiceDate.Date:= E.ValidDate
      else
        DTPickerTransactionDate.Date:= E.ValidDate;
    end;
    //tu ewentualne inne wyjatki które poza komunikatem wymagają obsługi
    on E: Exception do //pozostałe wyjątki
    begin
      Application.MessageBox(PWideChar(E.Message), PWideChar(Application.Title), MB_ICONERROR);
    end;
  end;
end;

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.