//----------------------------------------------------------------------------//
//- CaoArtikelListe.pas ------------------------------------------------------//
//----------------------------------------------------------------------------//

//- Beschreibung -------------------------------------------------------------//
// Die Unit CaoArtikelListe stellt zwei Klassen zur Verfügung:                //
// - Die Klasse TCaoArtikel, die einen Artikel kapselt                        //
// - Die Klasse TCaoArtikelListe, die eine Liste von TCaoArtikel kapselt      //
//----------------------------------------------------------------------------//

unit CaoArtikelListe;

//------------------------------------------------------------------------------

interface

//------------------------------------------------------------------------------

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs,
  CaoBaseClass, Contnrs;

//------------------------------------------------------------------------------

type
  TCaoArtikel = class(TObject)

  //----------------------------------------------------------------------------

  private
    m_dPreis           : Double;
    m_fVerkauft        : Boolean;
    m_iArtikelNummer   : Integer;
    m_sBeschreibung    : string;
    m_iStatus          : Integer;
    m_pAnbieter        : Pointer;
    m_iBoersenNummer   : Integer;

  //----------------------------------------------------------------------------

  public
    property dPreis         : Double
      read m_dPreis           write m_dPreis;
    property fVerkauft      : Boolean
      read m_fVerkauft        write m_fVerkauft;
    property iArtikelNummer : Integer
      read m_iArtikelNummer   write m_iArtikelNummer;
    property sBeschreibung  : string
      read m_sBeschreibung    write m_sBeschreibung;
    property iStatus        : Integer
      read m_iStatus          write m_iStatus;
    property pAnbieter      : Pointer
      read m_pAnbieter        write m_pAnbieter;
    property iBoersenNummer : Integer
      read m_iBoersenNummer   write m_iBoersenNummer;

    //--------------------------------------------------------------------------

    procedure   CopyArtikel      (const obArtikel: TCaoArtikel);

  //----------------------------------------------------------------------------

  end; // TCaoArtikel

//------------------------------------------------------------------------------

  TCaoArtikelListe = class (TCaoBaseClass)

  //----------------------------------------------------------------------------

  private
    m_iArtikelListenNummer: Integer;
    m_obListe             : TObjectList;

    //--------------------------------------------------------------------------

    function  GetdTotal                  : Double;
    function  PrvGetCount                : Integer;
    function  PrvGetItem(iIndex: Integer): TCaoArtikel;

  //----------------------------------------------------------------------------

  public
    constructor Create;                                    reintroduce;
    destructor  Destroy;                                   reintroduce; override;
    procedure   Free             (fFreeAllItems: Boolean); reintroduce;
    procedure   FreeAllItems;
    procedure   Sort             (Compare      : TListSortCompare);
    procedure   AddArtikel       (obArtikel    : TCaoArtikel);
    procedure   ArtikelVerkauft  (fVerkauft    : Boolean; iArtikelNummer: Integer);
    procedure   RemoveArtikel    (obArtikel    : TCaoArtikel);  overload;
    procedure   RemoveArtikel    (iPos         : Integer);      overload;
    procedure   DeleteArtikel    (obArtikel    : TCaoArtikel);
    procedure   InsertArtikel    (obArtikel    : TCaoArtikel;
                                  iPosition    : Integer);
    function    CopyAndAddArtikel(obArtikel    : TCaoArtikel): TCaoArtikel;
    function    CreateArtikel    : TCaoArtikel;
    procedure   SaveToDb;
    procedure   LoadFromDb       (iBoersenNummer: Integer);
    function    Locate           (iArtikelNummer: Integer): TCaoArtikel;
    procedure   CopyArtikelListe (const obArtikelListe: TCaoArtikelListe);
    procedure   SortByAnbieterNr;
    function    GetGewinn        (pPerson      : Pointer): Double; overload;
    function    GetGewinn: Double;                                 overload;
    function    GetTotalVerkauft      : Integer;
    function    GetTotalNichtVerkauft : Integer;
    function    GetGewinnFromBetrag (dAbgabeBetrag : Double): Double;
    function    GetGewinnFromProzent(dAbgabeProzent: Double): Double;

    property dTotal              : Double
      read GetdTotal;
    property iArtikelListenNummer: Integer
      read m_iArtikelListenNummer write  m_iArtikelListenNummer;
    property Count         : Integer
      read PrvGetCount;
    property Items[iIndex: Integer]: TCaoArtikel
      read PrvGetItem;
  end; //  TCaoArtikelListe

//------------------------------------------------------------------------------  

implementation

//------------------------------------------------------------------------------

uses
  CamConst, CaoDatenBank, CaoPersonenListe;

//------------------------------------------------------------------------------

var
  obDatenBank: TCaoDatenBank;

//------------------------------------------------------------------------------

function LocCompareAnbieter(obItem1, obItem2: Pointer): Integer;
(*
  Verleich der PersonenNummern der Anbieter.
  -> Wird für die Sortierung benötigt
*)
begin
  Result := TCaoPersonen(TCaoArtikel(obItem1).m_pAnbieter).iPersonenNummer -
            TCaoPersonen(TCaoArtikel(obItem2).m_pAnbieter).iPersonenNummer;
end; // LocCompareNummer

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.AddArtikel(obArtikel: TCaoArtikel);
begin
  m_obListe.Add(obArtikel);
end; // TCaoArtikelListe.AddArtikel

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.ArtikelVerkauft(fVerkauft: Boolean; iArtikelNummer: Integer);
begin
end; // TCaoArtikelListe.ArtikelVerkauft

//------------------------------------------------------------------------------

constructor TCaoArtikelListe.Create;
begin
  m_obListe := TObjectList.Create(False);
end; // TCaoArtikelListe.Create

//------------------------------------------------------------------------------

function TCaoArtikelListe.CreateArtikel: TCaoArtikel;
(*
  Kreiert ein Artikel-Objekt und hängt dieses der Artikelliste an
*)
var
  obArtikel: TCaoArtikel;
begin
  obArtikel := TCaoArtikel.Create;
  m_obListe.Add(obArtikel);
  Result := obArtikel;
end; // TCaoArtikelListe.CreateArtikel

//------------------------------------------------------------------------------

destructor TCaoArtikelListe.Destroy;
begin
  m_obListe.Free;
  inherited Destroy;
end; // TCaoArtikelListe.Destroy

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.Free(fFreeAllItems: Boolean);  
begin
  if fFreeAllItems then begin
    // Alle Artikelobjekte freigeben
    FreeAllItems;
  end; // if
  inherited Free;
end; // TCaoArtikelListe.Free

//------------------------------------------------------------------------------

function TCaoArtikelListe.GetdTotal: Double;
(*
  Zählt alle Preisbeträge der Liste zusammen, und gibt das Resultat aus
*)
var
  iIndex: Integer;
begin
  Result := 0;
  for iIndex := 0 to m_obListe.Count -1 do begin
    Result := Result + TCaoArtikel(m_obListe.Items[iIndex]).m_dPreis;
  end; // for
end; // TCaoArtikelListe.GetdTotal

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.RemoveArtikel(obArtikel: TCaoArtikel);
(*
  Löscht einen Artikel aus der Liste, das Objekt bleibt bestehen
*)
begin
  m_obListe.Extract(obArtikel);
end; // TCaoArtikelListe.DeleteArtikel

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.DeleteArtikel(obArtikel: TCaoArtikel);
(*
  Löscht einen Artikel aus der Liste und gib ihn frei
*)
begin
  RemoveArtikel(obArtikel);
  obArtikel.Free;
end; // TCaoArtikelListe.DeleteArtikel

//------------------------------------------------------------------------------

function TCaoArtikelListe.PrvGetCount: Integer;
begin
  Result := m_obListe.Count; 
end; // TCaoArtikelListe.PrvGetCount

//------------------------------------------------------------------------------

function TCaoArtikelListe.PrvGetItem(iIndex: Integer): TCaoArtikel;
begin
  Result := TCaoArtikel(m_obListe.Items[iIndex]);
end; // TCaoArtikelListe.PrvGetItem

//------------------------------------------------------------------------------

function TCaoArtikelListe.CopyAndAddArtikel(obArtikel: TCaoArtikel): TCaoArtikel;
var
  obArtikelCopy: TCaoArtikel;
begin
  obArtikelCopy := TCaoArtikel.Create;
  obArtikelCopy.dPreis            := obArtikel.dPreis;
  obArtikelCopy.fVerkauft         := obArtikel.fVerkauft;
  obArtikelCopy.iArtikelNummer    := obArtikel.iArtikelNummer;
  obArtikelCopy.sBeschreibung     := obArtikel.sBeschreibung;
  obArtikelCopy.iStatus           := obArtikel.iStatus;
  obArtikelCopy.pAnbieter         := obArtikel.pAnbieter;
  Self.AddArtikel(obArtikelCopy);
  Result                          := obArtikelCopy;
end; // TCaoArtikelListe.CopyAndAddArtikel

//------------------------------------------------------------------------------

procedure TCaoArtikel.CopyArtikel(const obArtikel: TCaoArtikel);
(*
  Die Daten ds Übergabeobjekts obArtikel werden in das Self -Objekt kopiert
*)
begin
  Self.dPreis         := obArtikel.dPreis;
  Self.sBeschreibung  := obArtikel.sBeschreibung;
  Self.pAnbieter      := obArtikel.pAnbieter; 
  Self.iStatus        := c_iModusCopy;
end; // TCaoArtikel.CopyArtikel

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.SaveToDb;
begin
  obDatenBank.SaveArtikelListe(Self);
end; // TCaoArtikelListe.SaveToDb

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.LoadFromDb(iBoersenNummer: Integer);
begin
  obDatenBank.LoadArtikelListe(Self, iBoersenNummer);
end; // TCaoArtikelListe.LoadFromDb

//------------------------------------------------------------------------------

function TCaoArtikelListe.Locate(iArtikelNummer: Integer): TCaoArtikel;
var
  iIndex: Integer;
begin
  Result := nil;
  for iIndex := 0 to m_obListe.Count -1 do begin
    if TCaoArtikel(m_obListe.Items[iIndex]).iArtikelNummer = iArtikelNummer then begin
      Result :=  TCaoArtikel(m_obListe.Items[iIndex]);
    end; // if
  end; // for
end; // TCaoArtikelListe.Locate

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.CopyArtikelListe(const obArtikelListe: TCaoArtikelListe);
(*
  Kopiert eine ganze ArtikelListe in das eigene Objekt
*)
var
  iIndex: Integer;
begin
  for iIndex := 0 to obArtikelListe.Count -1 do begin
    Self.CopyAndAddArtikel(obArtikelListe.Items[iIndex]);
  end; // for
end; // TCaoArtikelListe.CopyArtikelListe

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.InsertArtikel(obArtikel: TCaoArtikel;
                                         iPosition: Integer);
begin
  m_obListe.Insert(iPosition, obArtikel);
end; // TCaoArtikelListe.InsertArtikel

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.SortByAnbieterNr;
begin
  Self.Sort(@LocCompareAnbieter);
end; // TCaoArtikelListe.SortByAnbieterNr

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.Sort(Compare: TListSortCompare);
(*
  Sortieren der ArtikelListe
*)
begin
  m_obListe.Sort(Compare);
end; // TCaoArtikelListe.Sort

//------------------------------------------------------------------------------

function TCaoArtikelListe.GetGewinn(pPerson: Pointer): Double;
(*
  Gibt den das Total der verkauften Artikel einer Person zurück
*)
var
  iIndex: Integer;
begin
  Result := 0;
  for iIndex := 0 to Self.Count -1 do begin
    // In der Liste nach dem Anbieter suchen
    if Self.Items[iIndex].pAnbieter = pPerson then begin
      if Self.Items[iIndex].fVerkauft then begin
        Result := Result + Self.Items[iIndex].dPreis;
      end; // if
    end; // if
  end; // for
end; // TCaoArtikelListe.GetGewinn

//------------------------------------------------------------------------------

function TCaoArtikelListe.GetGewinn: Double;
(*
  Gibt das Total aller verkauften Artkiel zurück
*)
var
  iIndex: Integer;
begin
  Result := 0;
  for iIndex := 0 to m_obListe.Count -1 do begin
    if TCaoArtikel(m_obListe.Items[iIndex]).fVerkauft then begin
      Result := Result + TCaoArtikel(m_obListe.Items[iIndex]).m_dPreis;
    end; // if
  end; // for
end; // TCaoArtikelListe.GetdGewinn

//------------------------------------------------------------------------------

function TCaoArtikelListe.GetTotalNichtVerkauft: Integer;
(*
  Gibt die Anzahl der nicht verkauften Artikel zurück
*)
begin
  Result := Self.Count - Self.GetTotalVerkauft;
end; // TCaoArtikelListe.GetTotalNichtVerkauft

//------------------------------------------------------------------------------

function TCaoArtikelListe.GetTotalVerkauft: Integer;
(*
  Gibt die Anzahl der Verkauften Artikel zurück
*)
var
  iIndex: Integer;
begin
  Result := 0;
  for iIndex := 0 to Self.Count -1 do begin
    if Self.Items[iIndex].fVerkauft then begin
      inc(Result);
    end; // if
  end; // for
end; // TCaoArtikelListe.GetTotalVerkauft

//------------------------------------------------------------------------------

function TCaoArtikelListe.GetGewinnFromBetrag(dAbgabeBetrag: Double): Double;
(*
  Gibt den Gewinn, der durch die Einmalige Abgabe erzielt wurde zurück
*)
var
  obPersonenListe: TCaoPersonenListe;
  iIndex         : Integer;
begin
  Result := 0;
  // Es muss ein neues Objekt mit den Anbietern, von denen Artikel verkauft
  // wurden angelegt werden
  obPersonenListe := TCaoPersonenListe.Create;
  for iIndex := 0 to Self.Count -1 do begin
    if not obPersonenListe.IsPersonInListe
                         (TCaoPersonen(Self.Items[iIndex].pAnbieter)) then begin
      obPersonenListe.AddPerson(TCaoPersonen(Self.Items[iIndex].pAnbieter));
    end; // if
  end; // for
  for iIndex := 0 to obPersonenListe.Count -1 do begin
    if Self.GetGewinn(Pointer(obPersonenListe.Items[iIndex])) > dAbgabeBetrag then begin
      Result := Result + dAbgabeBetrag;
    end // if
    else begin
      Result := Result + Self.GetGewinn(Pointer(obPersonenListe.Items[iIndex]));
    end; // else
  end; // for
  obPersonenListe.Free(False);
end; // TCaoArtikelListe.GetGewinnFromBetrag

//------------------------------------------------------------------------------

function TCaoArtikelListe.GetGewinnFromProzent(dAbgabeProzent: Double): Double;
(*
  Gibt den Gewinn der abgezogenen Prozente zurück
*)
begin
  Result := Self.GetGewinn * (dAbgabeProzent / 100);
end; // TCaoArtikelListe.GetGewinnFromProzent

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.FreeAllItems;
(*
  Alle Objekte der Liste freigeben
*)
var
  iIndex: Integer;
begin
  for iIndex := 0 to m_obListe.Count - 1 do begin
    m_obListe.Items[iIndex].Free;
  end; // for
  m_obListe.Clear;
end; // TCaoArtikelListe.FreeAllItems

//------------------------------------------------------------------------------

procedure TCaoArtikelListe.RemoveArtikel(iPos: Integer);
(*
  Entfert den Artikel, der sich an der iPos-ten Position befindet
*)
begin
  if iPos <= m_obListe.Count then begin
    m_obListe.Delete(iPos);
  end; // if
end; // TCaoArtikelListe.RemoveArtikel

//------------------------------------------------------------------------------

end. // CaoArtikelListe
