unit rmCacheData;
// Report Memory Cache Data

interface

uses
  Classes, CacheTree, sdIDTree, sdDB;

type
  TDoubleArray = array of Double;
  TStringArray = array of string;

  TGclGatherNode = class
  private
    FB_Code: string;
    FIndexCode: string;
    FName: string;
    FUnits: string;
    FPrice: Double;

    FQuantity: Double;
    FTotalPrice: Double;

    FAddDealQuantity: Double;
    FAddDealTotalPrice: Double;
    FAddQcQuantity: Double;
    FAddQcTotalPrice: Double;
    FAddPcQuantity: Double;
    FAddPcTotalPrice: Double;

    FP_Price: TDoubleArray;
    FP_Quantity: TDoubleArray;
    FP_TotalPrice: TDoubleArray;
    FP_AddGatherQuantity: TDoubleArray;
    FP_AddGatherTotalPrice: TDoubleArray;

    procedure SetB_Code(const Value: string);
  public
    constructor Create(AProjectCount: Integer);

    property B_Code: string read FB_Code write SetB_Code;
    property IndexCode: string read FIndexCode;
    property Name: string read FName write FName;
    property Units: string read FUnits write FUnits;
    property Price: Double read FPrice write FPrice;

    property Quantity: Double read FQuantity write FQuantity;
    property TotalPrice: Double read FTotalPrice write FTotalPrice;

    property AddDealQuantity: Double read FAddDealQuantity write FAddDealQuantity;
    property AddDealTotalPrice: Double read FAddDealTotalPrice write FAddDealTotalPrice;
    property AddQcQuantity: Double read FAddQcQuantity write FAddQcQuantity;
    property AddQcTotalPrice: Double read FAddQcTotalPrice write FAddQcTotalPrice;
    property AddPcQuantity: Double read FAddPcQuantity write FAddPcQuantity;
    property AddPcTotalPrice: Double read FAddPcTotalPrice write FAddPcTotalPrice;

    property P_Price: TDoubleArray read FP_Price write FP_Price;
    property P_Quantity: TDoubleArray read FP_Quantity write FP_Quantity;
    property P_TotalPrice: TDoubleArray read FP_TotalPrice write FP_TotalPrice;
    property P_AddGatherQuantity: TDoubleArray read FP_AddGatherQuantity write FP_AddGatherQuantity;
    property P_AddGatherTotalPrice: TDoubleArray read FP_AddGatherTotalPrice write FP_AddGatherTotalPrice;
  end;

  TGclGatherList = class
  private
    FList: TList;
    FComparePrice: Boolean;
    FProjectName: TStringArray;
    FProjectCount: Integer;
    FGatherNode: TGclGatherNode;

    function SameGclNode(AGclNode: TGclGatherNode; ARec: TsdDataRecord): Boolean;

    function FindGclNode(ARec: TsdDataRecord): TGclGatherNode;
    function AddGclNode(ARec: TsdDataRecord): TGclGatherNode;

    function GetCount: Integer;
    function GetNode(AIndex: Integer): TGclGatherNode;
  public
    constructor Create(AProjectCount: Integer; AComparePrice: Boolean = True);
    destructor Destroy; override;

    function GetGclGatherNode(ARec: TsdDataRecord): TGclGatherNode;
    procedure ReCalcualteGatherNode;

    property ProjectCount: Integer read FProjectCount;
    property Count: Integer read GetCount;
    property Node[AIndex: Integer]: TGclGatherNode read GetNode;
    property GatherNode: TGclGatherNode read FGatherNode;
    property ProjectName: TStringArray read FProjectName write FProjectName;
  end;

  TFixedIDBillsNode = class
  private
    FFixedID: Integer;
    FName: string;
    FTotalPrice: Double;
    FP_TotalPrice: TDoubleArray;
    FAddGatherTotalPrice: Double;
    FP_AddGatherTotalPrice: TDoubleArray;
  public
    constructor Create(AProjectCount: Integer);

    property FixedID: Integer read FFixedID write FFixedID;
    property Name: string read FName write FName;
    property TotalPrice: Double read FTotalPrice write FTotalPrice;
    property P_TotalPrice: TDoubleArray read FP_TotalPrice write FP_TotalPrice;
    property AddGatherTotalPrice: Double read FAddGatherTotalPrice write FAddGatherTotalPrice;
    property P_AddGatherTotalPrice: TDoubleArray read FP_AddGatherTotalPrice write FP_AddGatherTotalPrice;
  end;

  TFixedIDBillsList = class
  private
    FList: TList;
    FProjectName: TStringArray;
    FProjectCount: Integer;

    function AddNode(AFixedID: Integer): TFixedIDBillsNode;

    function GetCount: Integer;
    function GetNode(AIndex: Integer): TFixedIDBillsNode;
  public
    constructor Create(AProjectCount: Integer);
    destructor Destroy; override;

    function GetFixedIDBillsNode(AFixedID: Integer): TFixedIDBillsNode;
    function FixedIDBillsNode(AFixedID: Integer): TFixedIDBillsNode;

    property ProjectCount: Integer read FProjectCount;
    property Count: Integer read GetCount;
    property Node[AIndex: Integer]: TFixedIDBillsNode read GetNode;
    property ProjectName: TStringArray read FProjectName write FProjectName;
  end;

implementation

uses
  ZhAPI, DateUtils, SysUtils, UtilMethods;

{ TGclGatherNode }

constructor TGclGatherNode.Create(AProjectCount: Integer);
begin
  SetLength(FP_Price, AProjectCount);
  SetLength(FP_Quantity, AProjectCount);
  SetLength(FP_TotalPrice, AProjectCount);
  SetLength(FP_AddGatherQuantity, AProjectCount);
  SetLength(FP_AddGatherTotalPrice, AProjectCount);
end;

procedure TGclGatherNode.SetB_Code(const Value: string);
begin
  FB_Code := Value;
  FIndexCode := B_CodeToIndexCode(FB_Code);
end;

{ TGclGatherList }

constructor TGclGatherList.Create(AProjectCount: Integer;
  AComparePrice: Boolean = True);
begin
  FProjectCount := AProjectCount;
  FList := TList.Create;
  FComparePrice := AComparePrice;
  SetLength(FProjectName, FProjectCount);
  FGatherNode := TGclGatherNode.Create(FProjectCount);
end;

destructor TGclGatherList.Destroy;
begin
  FGatherNode.Free;
  ClearObjects(FList);
  FList.Free;
  inherited;
end;

function TGclGatherList.FindGclNode(ARec: TsdDataRecord): TGclGatherNode;
var
  i: Integer;
  GclNode: TGclGatherNode;
begin
  Result := nil;
  for i := 0 to FList.Count - 1 do
  begin
    GclNode := TGclGatherNode(FList.Items[i]);
    if SameGclNode(GclNode, ARec) then
    begin
      Result := GclNode;
      Break;
    end;
  end;
end;

function TGclGatherList.GetCount: Integer;
begin
  Result := FList.Count;
end;

function TGclGatherList.GetNode(AIndex: Integer): TGclGatherNode;
begin
  Result := TGclGatherNode(FList.Items[AIndex]);
end;

function TGclGatherList.GetGclGatherNode(ARec: TsdDataRecord): TGclGatherNode;
begin
  Result := FindGclNode(ARec);
  if not Assigned(Result) then
    Result := AddGclNode(ARec);
end;

function TGclGatherList.AddGclNode(ARec: TsdDataRecord): TGclGatherNode;
begin
  Result := TGclGatherNode.Create(FProjectCount);
  FList.Add(Result);
  Result.B_Code := ARec.ValueByName('B_Code').AsString;
  Result.Name := ARec.ValueByName('Name').AsString;
  Result.Units := ARec.ValueByName('Units').AsString;
  Result.Price := ARec.ValueByName('Price').AsFloat;
end;

procedure TGclGatherList.ReCalcualteGatherNode;
var
  iNode, iP: Integer;
  GclNode: TGclGatherNode;
begin
  for iNode := 0 to FList.Count - 1 do
  begin
    GclNode := TGclGatherNode(FList.Items[iNode]);
    FGatherNode.Quantity := FGatherNode.Quantity + GclNode.Quantity;
    FGatherNode.TotalPrice := FGatherNode.TotalPrice + GclNode.TotalPrice;

    FGatherNode.AddDealQuantity := FGatherNode.AddDealQuantity + GclNode.AddDealQuantity;
    FGatherNode.AddDealTotalPrice := FGatherNode.AddDealTotalPrice + GclNode.AddDealTotalPrice;
    FGatherNode.AddQcQuantity := FGatherNode.AddQcQuantity + GclNode.AddQcQuantity;
    FGatherNode.AddQcTotalPrice := FGatherNode.AddQcTotalPrice + GclNode.AddQcTotalPrice;
    FGatherNode.AddPcQuantity := FGatherNode.AddPcQuantity + GclNode.AddPcQuantity;
    FGatherNode.AddPcTotalPrice := FGatherNode.AddPcTotalPrice + GclNode.AddPcTotalPrice;

    for iP := 0 to FProjectCount - 1 do
    begin
      FGatherNode.P_Quantity[iP] := FGatherNode.P_Quantity[iP] + GclNode.P_Quantity[iP];
      FGatherNode.P_TotalPrice[iP] := FGatherNode.P_TotalPrice[iP] + GclNode.P_TotalPrice[iP];
      FGatherNode.P_AddGatherQuantity[iP] := FGatherNode.P_AddGatherQuantity[iP] + GclNode.P_AddGatherQuantity[iP];
      FGatherNode.P_AddGatherTotalPrice[iP] := FGatherNode.P_AddGatherTotalPrice[iP] + GclNode.P_AddGatherTotalPrice[iP];
    end;
  end;
end;

function TGclGatherList.SameGclNode(AGclNode: TGclGatherNode; ARec: TsdDataRecord): Boolean;
begin
  Result := SameText(AGclNode.B_Code, ARec.ValueByName('B_Code').AsString) and
            SameText(AGclNode.Name, ARec.ValueByName('Name').AsString) and
            SameText(AGclNode.Units, ARec.ValueByName('Units').AsString);
  if FComparePrice then
    Result := Result and (AGclNode.Price = ARec.ValueByName('Price').AsFloat);
end;

{ TFixedIDBillsNode }

constructor TFixedIDBillsNode.Create(AProjectCount: Integer);
begin
  SetLength(FP_TotalPrice, AProjectCount);
  SetLength(FP_AddGatherTotalPrice, AProjectCount);
end;

{ TFixedIDBillsList }

function TFixedIDBillsList.AddNode(AFixedID: Integer): TFixedIDBillsNode;
begin
  Result := TFixedIDBillsNode.Create(FProjectCount);
  FList.Add(Result);
  Result.FixedID := AFixedID;
end;

constructor TFixedIDBillsList.Create(AProjectCount: Integer);
begin
  FProjectCount := AProjectCount;
  FList := TList.Create;
  SetLength(FProjectName, FProjectCount);
end;

destructor TFixedIDBillsList.Destroy;
begin
  ClearObjects(FList);
  FList.Free;
  inherited;
end;

function TFixedIDBillsList.FixedIDBillsNode(
  AFixedID: Integer): TFixedIDBillsNode;
var
  i: Integer;
begin
  Result := nil;
  for i := 0 to FList.Count - 1 do
  begin
    if TFixedIDBillsNode(FList.Items[i]).FixedID = AFixedID then
    begin
      Result := TFixedIDBillsNode(FList.Items[i]);
      Break;
    end;
  end;
end;

function TFixedIDBillsList.GetCount: Integer;
begin
  Result := FList.Count;
end;

function TFixedIDBillsList.GetFixedIDBillsNode(
  AFixedID: Integer): TFixedIDBillsNode;
begin
  Result := FixedIDBillsNode(AFixedID);
  if not Assigned(Result) then
    Result := AddNode(AFixedID);
end;

function TFixedIDBillsList.GetNode(AIndex: Integer): TFixedIDBillsNode;
begin
  Result := TFixedIDBillsNode(FList.Items[AIndex]);
end;

end.
