unit rmZhongKaiDm;
// 中开定制报表

interface

uses
  SysUtils, Classes, DB, DBClient, ProjectData, mDataRecord, sdDB,
  rmSelectProjectFrm, BillsTree;

type
  TGclNode = class
  private
    FB_Code: string;
    FIndexCode: string;
    FName: string;
    FUnits: string;
    FPrice: Double;
    FCalcType: Integer;

    FCTotalPrice: Double;

    FCurGatherQuantity: Double;
    FCurGatherTotalPrice: Double;
    FEndGatherQuantity: Double;
    FEndGatherTotalPrice: Double;
    FPreGatherQuantity: Double;
    FPreGatherTotalPrice: Double;

    FEndPqcQuantity: Double;
    FEndPqcTotalPrice: Double;
    FEndPqcaTotalPrice: Double;

    FEndMqcQuantity: Double;
    FEndMqcTotalPrice: Double;
    FEndMqcaTotalPrice: Double;

    FEndQcQuantity: Double;
    FEndQcTotalPrice: Double;
    FEndQcaTotalPrice: Double;

    FDealQuantity: Double;
    FDealTotalPrice: Double;
    procedure SetB_Code(const Value: string);
  public
    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 CalcType: Integer read FCalcType write FCalcType;

    property CurGatherQuantity: Double read FCurGatherQuantity write FCurGatherQuantity;
    property CurGatherTotalPrice: Double read FCurGatherTotalPrice write FCurGatherTotalPrice;
    property EndGatherQuantity: Double read FEndGatherQuantity write FEndGatherQuantity;
    property EndGatherTotalPrice: Double read FEndGatherTotalPrice write FEndGatherTotalPrice;
    property PreGatherQuantity: Double read FPreGatherQuantity write FPreGatherQuantity;
    property PreGatherTotalPrice: Double read FPreGatherTotalPrice write FPreGatherTotalPrice;

    property EndPqcQuantity: Double read FEndPqcQuantity write FEndPqcQuantity;
    property EndPqcTotalPrice: Double read FEndPqcTotalPrice write FEndPqcTotalPrice;
    property EndPqcaTotalPrice: Double read FEndPqcaTotalPrice write FEndPqcaTotalPrice;
    
    property EndMqcQuantity: Double read FEndMqcQuantity write FEndMqcQuantity;
    property EndMqcTotalPrice: Double read FEndMqcTotalPrice write FEndMqcTotalPrice;
    property EndMqcaTotalPrice: Double read FEndMqcaTotalPrice write FEndMqcaTotalPrice;

    property EndQcQuantity: Double read FEndQcQuantity write FEndQcQuantity;
    property EndQcTotalPrice: Double read FEndQcTotalPrice write FEndQcTotalPrice;
    property EndQcaTotalPrice: Double read FEndQcaTotalPrice write FEndQcaTotalPrice;

    property DealQuantity: Double read FDealQuantity write FDealQuantity;
    property DealTotalPrice: Double read FDealTotalPrice write FDealTotalPrice;
  end;

  TGclChapter = class
  private
    FGclNodes: TList;

    FChapterID: Integer;
    FChapterBegin: Integer;
    FChapterEnd: Integer;
    FChapterName: string;
    FName: string;

    FTotalPrice: Double;
    FCTotalPrice: Double;
    FGTotalPrice: Double;

    FCurGatherTotalPrice: Double;
    FEndGatherTotalPrice: Double;
    FPreGatherTotalPrice: Double;

    FEndPqcTotalPrice: Double;
    FEndPqcaTotalPrice: Double;
    FEndMqcTotalPrice: Double;
    FEndMqcaTotalPrice: Double;
    FEndQcTotalPrice: Double;
    FEndQcaTotalPrice: Double;
    FDealTotalPrice: Double;

    function GetCurPercent: Double;
    function GetEndPercent: Double;
    function GetPrePercent: Double;

    function GetGclNodeCount: Integer;
    function GetGclNode(AIndex: Integer): TGclNode;
  public
    constructor Create(AID: Integer; AName: string);
    destructor Destroy; override;

    procedure AddGclNode(AGclNode: TGclNode);
    procedure CalculateChapter;

    property ChapterID: Integer read FChapterID;
    property ChapterBegin: Integer read FChapterBegin;
    property ChapterEnd: Integer read FChapterEnd;
    property ChapterName: string read FChapterName;
    property Name: string read FName;

    property TotalPrice: Double read FTotalPrice write FTotalPrice;
    property CTotalPrice: Double read FCTotalPrice write FCTotalPrice;
    property GTotalPrice: Double read FGTotalPrice write FGTotalPrice;

    property CurGatherTotalPrice: Double read FCurGatherTotalPrice write FCurGatherTotalPrice;
    property EndGatherTotalPrice: Double read FEndGatherTotalPrice write FEndGatherTotalPrice;
    property PreGatherTotalPrice: Double read FPreGatherTotalPrice write FPreGatherTotalPrice;
    property CurPercent: Double read GetCurPercent;
    property EndPercent: Double read GetEndPercent;
    property PrePercent: Double read GetPrePercent;

    property EndPqcTotalPrice: Double read FEndPqcTotalPrice write FEndPqcTotalPrice;
    property EndPqcaTotalPrice: Double read FEndPqcaTotalPrice write FEndPqcaTotalPrice;

    property EndMqcTotalPrice: Double read FEndMqcTotalPrice write FEndMqcTotalPrice;
    property EndMqcaTotalPrice: Double read FEndMqcaTotalPrice write FEndMqcaTotalPrice;

    property EndQcTotalPrice: Double read FEndQcTotalPrice write FEndQcTotalPrice;
    property EndQcaTotalPrice: Double read FEndQcaTotalPrice write FEndQcaTotalPrice;

    property DealTotalPrice: Double read FDealTotalPrice write FDealTotalPrice;

    property GclNodeCount: Integer read GetGclNodeCount;
    property GclNode[AIndex: Integer]: TGclNode read GetGclNode;
  end;

  TGclControl = class
  private
    FGclNodes: TList;
    FGclChapters: TList;
    FOtherGcl: TGclChapter;
    FGclChapterGather: TGclChapter;

    function FindGclChapter(const AB_Code: string): TGclChapter;
    procedure LinkGclChapter(AGclNode: TGclNode);

    procedure CalculateChapterGather;

    function FindGclNode(ARec: TBillsRecord): TGclNode;
    function NewGclNode(ARec: TBillsRecord): TGclNode;

    function FindDealGclNode(ADealRec: TsdDataRecord): TGclNode;
    function NewDealGclNode(ADealRec: TsdDataRecord): TGclNode;

    function GetGclChapterCount: Integer;
    function GetGclChapter(AIndex: Integer): TGclChapter;
  public
    constructor Create;
    destructor Destroy; override;

    function AddGclNode(ARec: TBillsRecord; AStageRec: TStageRecord): TGclNode;
    procedure AddDealData(ARec: TsdDataRecord);

    procedure Calculate;

    property GclChapterCount: Integer read GetGclChapterCount;
    property GclChapter[AIndex: Integer]: TGclChapter read GetGclChapter;

    property OtherGcl: TGclChapter read FOtherGcl;
    property GclChapterGather: TGclChapter read FGclChapterGather;
  end;

  TPayNode = class
  private
    FName: string;

    FTotalPrice: Double;

    FCurTotalPrice: Double;
    FEndTotalPrice: Double;
    FPreTotalPrice: Double;
    function GetCurPercent: Double;
    function GetEndPercent: Double;
    function GetPrePercent: Double;
  public
    constructor Create(const AName: string);

    property Name: string read FName;

    property TotalPrice: Double read FTotalPrice write FTotalPrice;

    property CurTotalPrice: Double read FCurTotalPrice write FCurTotalPrice;
    property EndTotalPrice: Double read FEndTotalPrice write FEndTotalPrice;
    property PreTotalPrice: Double read FPreTotalPrice write FPreTotalPrice;
    property CurPercent: Double read GetCurPercent;
    property EndPercent: Double read GetEndPercent;
    property PrePercent: Double read GetPrePercent;
  end;

  TDealPayControl = class
  private
    FPreCalc: TPayNode;
    FTiaoPeiJin: TPayNode;
    FHeJi: TPayNode;
    FJiaGeTiaoZheng: TPayNode;
    FSuoPeiJinE: TPayNode;
    FLinShiYongDi: TPayNode;
    FBaoXianFei: TPayNode;
    FZongJi: TPayNode;

    FOtherPays: TList;
    FZhiFu: TPayNode;

    function FindOtherPayNode(const AName: string): TPayNode;
    function NewOtherPayNode(const AName: string): TPayNode;

    function GetOtherPay(AIndex: Integer): TPayNode;
    function GetOtherPayCount: Integer;
  public
    constructor Create;
    destructor Destroy; override;

    function FindPayNode(const AName: string): TPayNode;

    procedure CalculateAll;

    property PreCalc: TPayNode read FPreCalc;
    property TiaoPeiJin: TPayNode read FTiaoPeiJin;
    property HeJi: TPayNode read FHeJi;
    property JiaGeTiaoZheng: TPayNode read FJiaGeTiaoZheng;
    property SuoPeiJinE: TPayNode read FSuoPeiJinE;
    property LinShiYongDi: TPayNode read FLinShiYongDi;
    property BaoXianFei: TPayNode read FBaoXianFei;
    property ZongJi: TPayNode read FZongJi;

    property OtherPay[AIndex: Integer]: TPayNode read GetOtherPay;
    property OtherPayCount: Integer read GetOtherPayCount;
    property ZhiFu: TPayNode read FZhiFu;
  end;

  TZhongKaiGatherType = (zkgt2, zkgt3);

  TrmZhongKaiData = class(TDataModule)
    cdsCustom2: TClientDataSet;
    cdsCustom2ChapterID: TIntegerField;
    cdsCustom2Chapter: TWideStringField;
    cdsCustom2Name: TWideStringField;
    cdsCustom2TotalPrice: TFloatField;
    cdsCustom2CTotalPrice: TFloatField;
    cdsCustom2GTotalPrice: TFloatField;
    cdsCustom2EndGatherTotalPrice: TFloatField;
    cdsCustom2EndPercent: TFloatField;
    cdsCustom2PreGatherTotalPrice: TFloatField;
    cdsCustom2PrePercent: TFloatField;
    cdsCustom2CurGatherTotalPrice: TFloatField;
    cdsCustom2CurPercent: TFloatField;

    cdsCustom3: TClientDataSet;
    cdsCustom3ChapterID: TIntegerField;
    cdsCustom3IndexCode: TWideStringField;
    cdsCustom3B_Code: TWideStringField;
    cdsCustom3Name: TWideStringField;
    cdsCustom3Units: TWideStringField;
    cdsCustom3Price: TFloatField;
    cdsCustom3DealQuantity: TFloatField;
    cdsCustom3DealTotalPrice: TFloatField;
    cdsCustom3EndMqcQuantity: TFloatField;
    cdsCustom3EndMqcTotalPrice: TFloatField;
    cdsCustom3EndMqcaTotalPrice: TFloatField;
    cdsCustom3EndPqcQuantity: TFloatField;
    cdsCustom3EndPqcTotalPrice: TFloatField;
    cdsCustom3EndPqcaTotalPrice: TFloatField;
    cdsCustom3EndQcQuantity: TFloatField;
    cdsCustom3EndQcTotalPrice: TFloatField;
    cdsCustom3EndQcaTotalPrice: TFloatField;
    cdsCustom3GQuantity: TFloatField;
    cdsCustom3GTotalPrice: TFloatField;
    cdsCustom3EndGatherQuantity: TFloatField;
    cdsCustom3EndGatherTotalPrice: TFloatField;
    cdsCustom3PreGatherQuantity: TFloatField;
    cdsCustom3PreGatherTotalPrice: TFloatField;
    cdsCustom3CurGatherQuantity: TFloatField;
    cdsCustom3CurGatherTotalPrice: TFloatField;
  private
    FzkGatherType: TZhongKaiGatherType;
    FIsNewOpen: Boolean;
    FProjectData: TProjectData;
    FGclControl: TGclControl;
    FDealPayControl: TDealPayControl;

    procedure BeforeGather(AProjectCount: Integer);
    procedure AfterGather;

    procedure OpenProjectData(AProject: TSelectProject);
    procedure FreeProjectData;

    procedure FilterGcl;
    procedure FilterDealPay;
    procedure FilterDealBills;
    procedure GatherProject(AProject: TSelectProject);

    procedure WriteReport2;
    procedure WriteReport3;
    procedure WriteData;
  public
    function AssignData(AProjects: TList; AzkGatherType: TZhongKaiGatherType): TDataSet;
  end;

implementation

uses
  UtilMethods, ZhAPI, Globals, DealBillsDm;

{$R *.dfm}

{ TGclControl }

procedure TGclControl.AddDealData(ARec: TsdDataRecord);
var
  vGclNode: TGclNode;
begin
  vGclNode := FindDealGclNode(ARec);
  if not Assigned(vGclNode) then
    vGclNode := NewDealGclNode(ARec);
  vGclNode.DealQuantity := vGclNode.DealQuantity + ARec.ValueByName('Quantity').AsFloat;
  vGclNode.DealTotalPrice := vGclNode.DealTotalPrice + ARec.ValueByName('TotalPrice').AsFloat;
end;

function TGclControl.AddGclNode(ARec: TBillsRecord;
  AStageRec: TStageRecord): TGclNode;
begin
  Result := FindGclNode(ARec);
  if not Assigned(Result) then
    Result := NewGclNode(ARec);

  if Assigned(AStageRec) then
  begin
    Result.CurGatherQuantity := Result.CurGatherQuantity + AStageRec.GatherQuantity.AsFloat;
    Result.CurGatherTotalPrice := Result.CurGatherTotalPrice + AStageRec.GatherTotalPrice.AsFloat;

    Result.EndGatherQuantity := Result.EndGatherQuantity + AStageRec.EndGatherQuantity.AsFloat;
    Result.EndGatherTotalPrice := Result.EndGatherTotalPrice + AStageRec.EndGatherTotalPrice.AsFloat;

    Result.PreGatherQuantity := Result.PreGatherQuantity + AStageRec.PreGatherQuantity.AsFloat;
    Result.PreGatherTotalPrice := Result.PreGatherTotalPrice + AStageRec.PreGatherTotalPrice.AsFloat;
  end;
end;

procedure TGclControl.Calculate;
var
  i: Integer;
begin
  for i := 0 to FGclChapters.Count - 1 do
    GclChapter[i].CalculateChapter;
  OtherGcl.CalculateChapter;
  CalculateChapterGather;  
end;

procedure TGclControl.CalculateChapterGather;
var
  iIndex, iProject: Integer;
  vGclChapter: TGclChapter;
begin
  FGclChapterGather.TotalPrice := 0;
  FGclChapterGather.CurGatherTotalPrice := 0;
  FGclChapterGather.EndGatherTotalPrice := 0;
  FGclChapterGather.PreGatherTotalPrice := 0;

  for iIndex := 0 to FGclChapters.Count - 1 do
  begin
    vGclChapter := TGclChapter(FGclChapters.Items[iIndex]);
    with FGclChapterGather do
    begin
      TotalPrice := TotalPrice + vGclChapter.TotalPrice;
      CTotalPrice := CTotalPrice + vGclChapter.CTotalPrice;
      CurGatherTotalPrice := CurGatherTotalPrice + vGclChapter.CurGatherTotalPrice;
      EndGatherTotalPrice := EndGatherTotalPrice + vGclChapter.EndGatherTotalPrice;
      PreGatherTotalPrice := PreGatherTotalPrice + vGclChapter.PreGatherTotalPrice;
    end;
  end;
  with FGclChapterGather do
  begin
    TotalPrice := TotalPrice + OtherGcl.TotalPrice;        
    CTotalPrice := CTotalPrice + OtherGcl.CTotalPrice;
    CurGatherTotalPrice := CurGatherTotalPrice + OtherGcl.CurGatherTotalPrice;
    EndGatherTotalPrice := EndGatherTotalPrice + OtherGcl.EndGatherTotalPrice;
    PreGatherTotalPrice := PreGatherTotalPrice + OtherGcl.PreGatherTotalPrice;
  end;
end;

constructor TGclControl.Create;

  function CreateGclChapter(AChapterID: Integer; const AName: string; ATotalPrice: Double): TGclChapter;
  begin
    Result := TGclChapter.Create(AChapterID, AName);
    Result.TotalPrice := ATotalPrice;
    FGclChapters.Add(Result);
  end;

begin
  FGclNodes := TList.Create;

  FGclChapters := TList.Create;
  CreateGclChapter(1, '总则', 381525229);
  CreateGclChapter(2, '路基工程', 1514953910);
  CreateGclChapter(3, '路面工程', 796118656);
  CreateGclChapter(4, '桥梁、涵洞工程', 4912677553);
  CreateGclChapter(5, '隧道工程', 0);
  CreateGclChapter(6, '安全设施及预埋管线', 165165432);
  CreateGclChapter(7, '绿化及环境保护工程', 163726129);
  CreateGclChapter(8, '机电工程', 273752856);
  CreateGclChapter(9, '附属区房建工程', 160025390);

  FOtherGcl := TGclChapter.Create(19, '未计入章节清单合计');
  FOtherGcl.TotalPrice := 0;

  FGclChapterGather := TGclChapter.Create(20, '小计');
  FGclChapterGather.TotalPrice := 8367944755;
end;

destructor TGclControl.Destroy;
begin
  FGclChapterGather.Free;
  FOtherGcl.Free;
  ClearObjects(FGclChapters);
  FGclChapters.Free;
  ClearObjects(FGclNodes);
  FGclNodes.Free;
  inherited;
end;

function TGclControl.FindDealGclNode(ADealRec: TsdDataRecord): TGclNode;
var
  iIndex: Integer;
  vGclNode: TGclNode;
begin
  Result := nil;
  for iIndex := 0 to FGclNodes.Count - 1 do
  begin
    vGclNode := TGclNode(FGclNodes.Items[iIndex]);

    if (vGclNode.B_Code = ADealRec.ValueByName('B_Code').AsString) and
        (vGclNode.Name = ADealRec.ValueByName('Name').AsString) and
        (vGclNode.Units = ADealRec.ValueByName('Units').AsString) and
        (vGclNode.Price = ADealRec.ValueByName('Price').AsFloat) then
      begin
        Result := vGclNode;
        Break;
      end;
  end;
end;

function TGclControl.FindGclChapter(const AB_Code: string): TGclChapter;

  function GetFirstLevelCode: string;
  var
    sgs: TStrings;
  begin
    sgs := TStringList.Create; 
    sgs.Delimiter := '-';
    sgs.DelimitedText := AB_Code;
    if sgs.Count > 0 then
      Result := sgs.Strings[0]
    else
      Result := '';
    sgs.Free;
  end;

var
  iFirst, iIndex: Integer;
  vChapter: TGclChapter;
begin
  iFirst := StrToIntDef(GetFirstLevelCode, 0);
  Result := nil;
  for iIndex := 0 to FGclChapters.Count - 1 do
  begin
    vChapter := TGclChapter(FGclChapters.Items[iIndex]);
    if (iFirst >= vChapter.ChapterBegin) and (iFirst <= vChapter.ChapterEnd) then
    begin
      Result := vChapter;
      Break;
    end;
  end;
end;

function TGclControl.FindGclNode(ARec: TBillsRecord): TGclNode;
var
  iIndex: Integer;
  vGclNode: TGclNode;
  bSameCode, bSameName, bSameUnits, bSamePrice: Boolean;
begin
  Result := nil;
  for iIndex := 0 to FGclNodes.Count - 1 do
  begin
    vGclNode := TGclNode(FGclNodes.Items[iIndex]);

    if (vGclNode.B_Code = ARec.B_Code.AsString) and
        (vGclNode.Name = ARec.Name.AsString) and
        (vGclNode.Units = ARec.Units.AsString) and
        (vGclNode.Price = ARec.Price.AsFloat) then
      begin
        Result := vGclNode;
        Break;
      end;
  end;
end;

function TGclControl.GetGclChapter(AIndex: Integer): TGclChapter;
begin
  Result := TGclChapter(FGclChapters.Items[AIndex]);
end;

function TGclControl.GetGclChapterCount: Integer;
begin
  Result := FGclChapters.Count;
end;

procedure TGclControl.LinkGclChapter(AGclNode: TGclNode);
var
  vChapter: TGclChapter;
begin
  vChapter := FindGclChapter(AGclNode.B_Code);
  if Assigned(vChapter) then
    vChapter.AddGclNode(AGclNode)
  else
    FOtherGcl.AddGclNode(AGclNode);
end;

function TGclControl.NewDealGclNode(ADealRec: TsdDataRecord): TGclNode;
begin
  Result := TGclNode.Create;
  FGclNodes.Add(Result);
  Result.B_Code := ADealRec.ValueByName('B_Code').AsString;
  Result.Name := ADealRec.ValueByName('Name').AsString;
  Result.Units := ADealRec.ValueByName('Units').AsString;
  Result.Price := ADealRec.ValueByName('Price').AsFloat;
  LinkGclChapter(Result);
end;

function TGclControl.NewGclNode(ARec: TBillsRecord): TGclNode;
begin
  Result := TGclNode.Create;
  FGclNodes.Add(Result);
  Result.B_Code := ARec.B_Code.AsString;
  Result.Name := ARec.Name.AsString;
  Result.Units := ARec.Units.AsString;
  Result.Price := ARec.Price.AsFloat;
  Result.CalcType := ARec.CalcType.AsInteger;
  LinkGclChapter(Result);
end;

{ TGclChapter }

procedure TGclChapter.AddGclNode(AGclNode: TGclNode);
begin
  FGclNodes.Add(AGclNode);
end;

procedure TGclChapter.CalculateChapter;
var
  iIndex: Integer;
  vGclNode: TGclNode;
begin
  FCTotalPrice := 0;
  FCurGatherTotalPrice := 0;
  FEndGatherTotalPrice := 0;
  FPreGatherTotalPrice := 0;
  FEndPqcTotalPrice := 0;
  FEndPqcaTotalPrice := 0;
  FEndMqcTotalPrice := 0;
  FEndMqcaTotalPrice := 0;
  FEndQcTotalPrice := 0;
  FEndQcaTotalPrice := 0;
  FDealTotalPrice := 0;

  for iIndex := 0 to FGclNodes.Count - 1 do
  begin
    vGclNode := TGclNode(FGclNodes.Items[iIndex]);
    FCTotalPrice := FCTotalPrice + vGclNode.EndQcTotalPrice;
    FCurGatherTotalPrice := FCurGatherTotalPrice + vGclNode.FCurGatherTotalPrice;
    FEndGatherTotalPrice := FEndGatherTotalPrice + vGclNode.FEndGatherTotalPrice;
    FPreGatherTotalPrice := FPreGatherTotalPrice + vGclNode.FPreGatherTotalPrice;

    FEndPqcTotalPrice := FEndPqcTotalPrice + vGclNode.FEndPqcTotalPrice;
    FEndPqcaTotalPrice := FEndPqcaTotalPrice + vGclNode.FEndPqcaTotalPrice;
    FEndMqcTotalPrice := FEndMqcTotalPrice + vGclNode.FEndMqcTotalPrice;
    FEndMqcaTotalPrice := FEndMqcaTotalPrice + vGclNode.FEndMqcaTotalPrice;
    FEndQcTotalPrice := FEndQcTotalPrice + vGclNode.FEndQcTotalPrice;
    FEndQcaTotalPrice := FEndQcaTotalPrice + vGclNode.FEndQcaTotalPrice;
    FDealTotalPrice := FDealTotalPrice + vGclNode.FDealTotalPrice;
  end;

  FGTotalPrice := FTotalPrice + FCTotalPrice;
end;

constructor TGclChapter.Create(AID: Integer; AName: string);
begin
  FChapterID := AID;
  FName := AName;
  if FChapterID < 19 then
  begin
    FChapterBegin := FChapterID * 100;
    FChapterEnd := FChapterBegin + 99;
    FChapterName := IntToStr(FChapterBegin);
  end;
  FGclNodes := TList.Create;
end;

destructor TGclChapter.Destroy;
begin
  FGclNodes.Free;
  inherited;
end;

function TGclChapter.GetCurPercent: Double;
begin
  if FGTotalPrice = 0 then
    Result := 0
  else
    Result := FCurGatherTotalPrice / FGTotalPrice * 100;
end;

function TGclChapter.GetEndPercent: Double;
begin
  if FGTotalPrice = 0 then
    Result := 0
  else
    Result := FEndGatherTotalPrice / FGTotalPrice * 100;
end;

function TGclChapter.GetGclNode(AIndex: Integer): TGclNode;
begin
  Result := TGclNode(FGclNodes.Items[AIndex]);
end;

function TGclChapter.GetGclNodeCount: Integer;
begin
  Result := FGclNodes.Count;
end;

function TGclChapter.GetPrePercent: Double;
begin
  if FGTotalPrice = 0 then
    Result := 0
  else
    Result := FPreGatherTotalPrice / FGTotalPrice * 100;
end;

{ TrmZhongKaiData }

procedure TrmZhongKaiData.AfterGather;
begin
  FDealPayControl.Free;
  FGclControl.Free;
end;

function TrmZhongKaiData.AssignData(AProjects: TList;
  AzkGatherType: TZhongKaiGatherType): TDataSet;
var
  iProject: Integer;
begin
  FzkGatherType := AzkGatherType;
  BeforeGather(AProjects.Count);
  try
    for iProject := 0 to AProjects.Count - 1 do
      GatherProject(TSelectProject(AProjects.Items[iProject]));
    FGclControl.Calculate;
    WriteData;
  finally
    AfterGather;
    case FzkGatherType of
      zkgt2: Result := cdsCustom2;
      zkgt3: Result := cdsCustom3;
    end;
  end;
end;

procedure TrmZhongKaiData.BeforeGather(AProjectCount: Integer);
begin
  cdsCustom2.DisableControls;
  cdsCustom2.Active := True;
  cdsCustom2.EmptyDataSet;

  cdsCustom3.DisableControls;
  cdsCustom3.Active := True;
  cdsCustom3.EmptyDataSet;

  FGclControl := TGclControl.Create;
  FDealPayControl := TDealPayControl.Create;
end;

procedure TrmZhongKaiData.FilterGcl;

  function FindStage(AID: Integer; AList: TList): TStageRecord;
  var
    i: Integer;
    Rec: TStageRecord;
  begin
    Result := nil;
    for i := 0 to AList.Count - 1 do
    begin
      Rec :=  TStageRecord(AList.Items[i]);
      if Rec.BillsID.AsInteger = AID then
      begin
        Result := Rec;
        Break;
      end;
    end;
  end;

  procedure FilterNewOpened;
  var
    vList: TList;
    i: Integer;
    GclNode: TGclNode;
    Rec: TBillsRecord;
    StageRec: TStageRecord;
  begin
    vList := TList.Create;
    try
      with FProjectData.PhaseData.StageData do
      begin
        for i := 0 to sddStage.RecordCount - 1 do
          vList.Add(sddStage.Records[i]);
      end;

      FProjectData.BillsData.sddBills.DisableControls;
      FProjectData.PhaseData.StageData.sddStage.DisableControls;
      with FProjectData.BillsData do
      begin
        for i := 0 to sddBills.RecordCount - 1 do
        begin
          Rec := TBillsRecord(sddBills.Records[i]);
          if Rec.IsLeaf.AsBoolean and (Rec.B_Code.AsString <> '') then
          begin
            StageRec := FindStage(Rec.ID.AsInteger, vList);
            GclNode := FGclControl.AddGclNode(Rec, StageRec);
            vList.Remove(StageRec);
          end;
        end;
      end;
    finally
      vList.Free;
    end;
  end;

  procedure FilterOrg;
  var
    i: Integer;
    vNode: TMeasureBillsIDTreeNode;
    GclNode: TGclNode;
    StageRec: TStageRecord;
  begin
    with FProjectData.BillsMeasureData do
    begin
      for i := 0 to BillsMeasureTree.Count - 1 do
      begin
        vNode := TMeasureBillsIDTreeNode(BillsMeasureTree.Items[i]);
        if not vNode.HasChildren and (vNode.Rec.B_Code.AsString <> '') then
          GclNode := FGclControl.AddGclNode(vNode.Rec, vNode.StageRec);
      end;
    end;
  end;

begin
  if FIsNewOpen then
    FilterNewOpened
  else
    FilterOrg;
end;

procedure TrmZhongKaiData.FilterDealPay;
var
  sCurField, sPreField, sEndField: string;

  procedure GatherCommonDealPay;
  var
    iRec: Integer;
    Rec, StageRec: TsdDataRecord;
    DealPay: TPayNode;
  begin
    with FProjectData.DealPaymentData do
    begin
      for iRec := 0 to sddDealPayment.RecordCount - 1 do
      begin
        Rec := sddDealPayment.Records[iRec];
        if SameText(Rec.ValueByName('Name').AsString, '本期完成计量') or
           SameText(Rec.ValueByName('Name').AsString, '本期应付') or
           SameText(Rec.ValueByName('Name').AsString, '本期实付') then
          Continue;
        if FProjectData.PhaseData.Active then
          StageRec := FProjectData.PhaseData.PhasePayData.PayRecord(Rec.ValueByName('ID').AsInteger)
        else
          StageRec := nil;

        DealPay := FDealPayControl.FindPayNode(Rec.ValueByName('Name').AsString);
        if Assigned(StageRec) then
        begin
          DealPay.CurTotalPrice := DealPay.CurTotalPrice + StageRec.ValueByName(sCurField).AsFloat;
          DealPay.PreTotalPrice := DealPay.PreTotalPrice + StageRec.ValueByName(sPreField).AsFloat;
          DealPay.EndTotalPrice := DealPay.EndTotalPrice + StageRec.ValueByName(sEndField).AsFloat;
        end;
      end;
    end;
  end;

  procedure GatherZhiFu;
  var
    Rec, StageRec: TsdDataRecord;
  begin
    Rec := FProjectData.DealPaymentData.DealPayRecord('本期应付');
    if FProjectData.PhaseData.Active then
      StageRec := FProjectData.PhaseData.PhasePayData.PayRecord(Rec.ValueByName('ID').AsInteger)
    else
      StageRec := nil;

    if not Assigned(StageRec) then Exit;

    with FDealPayControl.ZhiFu do
    begin
      CurTotalPrice := CurTotalPrice + StageRec.ValueByName(sCurField).AsFloat;
      PreTotalPrice := PreTotalPrice + StageRec.ValueByName(sPreField).AsFloat;
      EndTotalPrice := EndTotalPrice + StageRec.ValueByName(sEndField).AsFloat;
    end;
  end;

begin
  sCurField := 'TotalPrice' + IntToStr(FProjectData.PhaseData.AuditCount);
  sPreField := 'PreTotalPrice' + IntToStr(FProjectData.PhaseData.AuditCount);
  sEndField := 'EndTotalPrice' + IntToStr(FProjectData.PhaseData.AuditCount);
  GatherCommonDealPay;
  GatherZhiFu;
  FDealPayControl.CalculateAll;
end;

procedure TrmZhongKaiData.FreeProjectData;
begin
  if FIsNewOpen then
    FProjectData.Free;
end;

procedure TrmZhongKaiData.GatherProject(AProject: TSelectProject);
begin
  OpenProjectData(AProject);
  try
    if FzkGatherType in [zkgt2, zkgt3] then
      FilterGcl;
    if FzkGatherType = zkgt2 then
      FilterDealPay;
    if FzkGatherType = zkgt3 then
      FilterDealBills;
  finally
    FreeProjectData;
  end;
end;

procedure TrmZhongKaiData.OpenProjectData(AProject: TSelectProject);
var
  Rec: TsdDataRecord;
begin
  FIsNewOpen := False;
  FProjectData := OpenProjectManager.FindProjectData(AProject.ProjectID);
  Rec := ProjectManager.sddProjectsInfo.FindKey('idxID', AProject.ProjectID);
  if not Assigned(FProjectData) then
  begin
    FProjectData := TProjectData.Create;
    FProjectData.OpenForReport4(GetMyProjectsFilePath + Rec.ValueByName('FileName').AsString);
    FIsNewOpen := True;
  end;
end;

procedure TrmZhongKaiData.WriteData;
begin
  case FzkGatherType of
    zkgt2: WriteReport2;
    zkgt3: WriteReport3;
  end;
end;

procedure TrmZhongKaiData.WriteReport2;

  procedure WriteGclChapter(AGclChapter: TGclChapter);
  begin
    cdsCustom2.Append;
    cdsCustom2ChapterID.AsInteger := AGclChapter.ChapterID;
    cdsCustom2Chapter.AsString := AGclChapter.ChapterName;
    cdsCustom2Name.AsString := AGclChapter.Name;
    cdsCustom2TotalPrice.AsFloat := AGclChapter.TotalPrice;
    cdsCustom2CTotalPrice.AsFloat := AGclChapter.CTotalPrice;
    cdsCustom2GTotalPrice.AsFloat := AGclChapter.GTotalPrice;
    cdsCustom2EndGatherTotalPrice.AsFloat := AGclChapter.EndGatherTotalPrice;
    cdsCustom2EndPercent.AsFloat := AGclChapter.EndPercent;
    cdsCustom2PreGatherTotalPrice.AsFloat := AGclChapter.PreGatherTotalPrice;
    cdsCustom2PrePercent.AsFloat := AGclChapter.PrePercent;
    cdsCustom2CurGatherTotalPrice.AsFloat := AGclChapter.CurGatherTotalPrice;
    cdsCustom2CurPercent.AsFloat := AGclChapter.CurPercent;
    cdsCustom2.Post;
  end;

  procedure WritePayNode(APayNode: TPayNode);
  begin
    cdsCustom2.Append;
    cdsCustom2Name.AsString := APayNode.Name;
    cdsCustom2TotalPrice.AsFloat := APayNode.TotalPrice;
    cdsCustom2CurGatherTotalPrice.AsFloat := APayNode.CurTotalPrice;
    cdsCustom2PreGatherTotalPrice.AsFloat := APayNode.PreTotalPrice;
    cdsCustom2EndGatherTotalPrice.AsFloat := APayNode.EndTotalPrice;
    cdsCustom2.Post;
  end;

var
  iIndex: Integer;
begin
  for iIndex := 0 to FGclControl.GclChapterCount - 1 do
    WriteGclChapter(FGclControl.GclChapter[iIndex]);
  if FGclControl.OtherGcl.GclNodeCount > 0 then
    WriteGclChapter(FGclControl.OtherGcl);
  WriteGclChapter(FGclControl.GclChapterGather);

  WritePayNode(FDealPayControl.TiaoPeiJin);
  WritePayNode(FDealPayControl.HeJi);
  WritePayNode(FDealPayControl.JiaGeTiaoZheng);
  WritePayNode(FDealPayControl.SuoPeiJinE);
  WritePayNode(FDealPayControl.LinShiYongDi);
  WritePayNode(FDealPayControl.BaoXianFei);
  WritePayNode(FDealPayControl.ZongJi);
  for iIndex := 0 to FDealPayControl.OtherPayCount - 1 do
    WritePayNode(FDealPayControl.OtherPay[iIndex]);
  WritePayNode(FDealPayControl.ZhiFu);
end;

procedure TrmZhongKaiData.WriteReport3;

  procedure WriteGclNode(AGclNode: TGclNode; AChapterID: Integer);
  begin
    cdsCustom3.Append;
    cdsCustom3ChapterID.AsInteger := AChapterID;
    cdsCustom3IndexCode.AsString := AGclNode.IndexCode;
    cdsCustom3B_Code.AsString := AGclNode.B_Code;
    cdsCustom3Name.AsString := AGclNode.Name;
    cdsCustom3Units.AsString := AGclNode.Units;
    cdsCustom3Price.AsFloat := AGclNode.Price;

    cdsCustom3DealQuantity.AsFloat := AGclNode.DealQuantity;
    cdsCustom3DealTotalPrice.AsFloat := AGclNode.DealTotalPrice;

    cdsCustom3EndMqcQuantity.AsFloat := AGclNode.EndMqcQuantity;
    cdsCustom3EndMqcTotalPrice.AsFloat := AGclNode.EndMqcTotalPrice;
    cdsCustom3EndMqcaTotalPrice.AsFloat := AGclNode.EndMqcaTotalPrice;

    cdsCustom3EndPqcQuantity.AsFloat := AGclNode.EndPqcQuantity;
    cdsCustom3EndPqcTotalPrice.AsFloat := AGclNode.EndPqcTotalPrice;
    cdsCustom3EndPqcaTotalPrice.AsFloat := AGclNode.EndPqcaTotalPrice;

    cdsCustom3EndQcQuantity.AsFloat := AGclNode.EndQcQuantity;
    cdsCustom3EndQcTotalPrice.AsFloat := AGclNode.EndQcTotalPrice;
    cdsCustom3EndQcaTotalPrice.AsFloat := AGclNode.EndQcaTotalPrice;

    cdsCustom3GQuantity.AsFloat := cdsCustom3DealQuantity.AsFloat + cdsCustom3EndQcQuantity.AsFloat;
    cdsCustom3GTotalPrice.AsFloat := cdsCustom3DealTotalPrice.AsFloat + cdsCustom3EndQcaTotalPrice.AsFloat;

    cdsCustom3EndGatherQuantity.AsFloat := AGclNode.EndGatherQuantity;
    cdsCustom3EndGatherTotalPrice.AsFloat := AGclNode.EndGatherTotalPrice;

    cdsCustom3PreGatherQuantity.AsFloat := AGclNode.PreGatherQuantity;
    cdsCustom3PreGatherTotalPrice.AsFloat := AGclNode.PreGatherTotalPrice;

    cdsCustom3CurGatherQuantity.AsFloat := AGclNode.CurGatherQuantity;
    cdsCustom3CurGatherTotalPrice.AsFloat := AGclNode.CurGatherTotalPrice;
    cdsCustom3.Post;
  end;

  procedure WriteChapter(AGclChapter: TGclChapter; const AName: string = '');
  var
    i: Integer;
  begin
    cdsCustom3.Append;
    cdsCustom3ChapterID.AsInteger := AGclChapter.ChapterID;
    if AGclChapter.ChapterName <> '' then
      cdsCustom3B_Code.AsString := AGclChapter.ChapterName + '章';
    if AName = '' then
      cdsCustom3Name.AsString := AGclChapter.Name
    else
      cdsCustom3Name.AsString := AName;

    cdsCustom3DealTotalPrice.AsFloat := AGclChapter.DealTotalPrice;

    cdsCustom3EndMqcTotalPrice.AsFloat := AGclChapter.EndMqcTotalPrice;
    cdsCustom3EndMqcaTotalPrice.AsFloat := AGclChapter.EndMqcaTotalPrice;

    cdsCustom3EndPqcTotalPrice.AsFloat := AGclChapter.EndPqcTotalPrice;
    cdsCustom3EndPqcaTotalPrice.AsFloat := AGclChapter.EndPqcaTotalPrice;

    cdsCustom3EndQcTotalPrice.AsFloat := AGclChapter.EndQcTotalPrice;
    cdsCustom3EndQcaTotalPrice.AsFloat := AGclChapter.EndQcaTotalPrice;

    cdsCustom3GTotalPrice.AsFloat := cdsCustom3DealTotalPrice.AsFloat + cdsCustom3EndQcaTotalPrice.AsFloat;

    cdsCustom3EndGatherTotalPrice.AsFloat := AGclChapter.EndGatherTotalPrice;

    cdsCustom3PreGatherTotalPrice.AsFloat := AGclChapter.PreGatherTotalPrice;

    cdsCustom3CurGatherTotalPrice.AsFloat := AGclChapter.CurGatherTotalPrice;
    cdsCustom3.Post;
    for i := 0 to AGclChapter.GclNodeCount - 1 do
      WriteGclNode(AGclChapter.GclNode[i], AGclChapter.ChapterID);
  end;

var
  iIndex: Integer;
begin
  for iIndex := 0 to FGclControl.GclChapterCount - 1 do
    WriteChapter(FGclControl.GclChapter[iIndex]);
  if FGclControl.OtherGcl.GclNodeCount > 0 then
    WriteChapter(FGclControl.OtherGcl);
  WriteChapter(FGclControl.GclChapterGather, '合计');
end;

procedure TrmZhongKaiData.FilterDealBills;
var
  i: Integer;
  Rec: TsdDataRecord;
begin
  with FProjectData.DealBillsData do
  begin
    for i := 0 to sddDealBills.RecordCount - 1 do
    begin
      Rec := sddDealBills.Records[i];
      
    end;
  end;
end;

{ TGclNode }

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

{ TPayNode }

constructor TPayNode.Create(const AName: string);
begin
  FName := AName;
end;

function TPayNode.GetCurPercent: Double;
begin
  if TotalPrice = 0 then
    Result := 0
  else
    Result := CurTotalPrice / TotalPrice * 100;
end;

function TPayNode.GetEndPercent: Double;
begin
  if TotalPrice = 0 then
    Result := 0
  else
    Result := EndTotalPrice / TotalPrice * 100;
end;

function TPayNode.GetPrePercent: Double;
begin
  if TotalPrice = 0 then
    Result := 0
  else
    Result := PreTotalPrice / TotalPrice * 100;
end;

{ TDealPayControl }

function TDealPayControl.FindPayNode(const AName: string): TPayNode;
begin
 if Pos(FTiaoPeiJin.Name, AName) > 0 then
    Result := FTiaoPeiJin
  else if Pos(FJiaGeTiaoZheng.Name, AName) > 0 then
    Result := FJiaGeTiaoZheng
  else if Pos(FSuoPeiJinE.Name, AName) > 0 then
    Result := FSuoPeiJinE
  else if Pos(FLinShiYongDi.Name, AName) > 0 then
    Result := FLinShiYongDi
  else if Pos(FBaoXianFei.Name, AName) > 0 then
    Result := FBaoXianFei
  else
    Result := FindOtherPayNode(AName);
  if not Assigned(Result) then
    Result := NewOtherPayNode(AName);
end;

procedure TDealPayControl.CalculateAll;

  procedure CalculateHeJi;
  begin
    FHeJi.TotalPrice := FPreCalc.TotalPrice + FTiaoPeiJin.TotalPrice;
    FHeJi.CurTotalPrice := FPreCalc.CurTotalPrice + FTiaoPeiJin.CurTotalPrice;
    FHeJi.EndTotalPrice := FPreCalc.EndTotalPrice + FTiaoPeiJin.EndTotalPrice;
    FHeJi.PreTotalPrice := FPreCalc.PreTotalPrice + FTiaoPeiJin.PreTotalPrice;
  end;

  procedure CalculateZongJi;
  begin
    FZongJi.TotalPrice := FHeJi.TotalPrice + FJiaGeTiaoZheng.TotalPrice +
        FSuoPeiJinE.TotalPrice + FLinShiYongDi.TotalPrice + FBaoXianFei.TotalPrice;
    FZongJi.CurTotalPrice := FHeJi.CurTotalPrice + FJiaGeTiaoZheng.CurTotalPrice +
        FSuoPeiJinE.CurTotalPrice + FLinShiYongDi.CurTotalPrice + FBaoXianFei.CurTotalPrice;
    FZongJi.EndTotalPrice := FHeJi.EndTotalPrice + FJiaGeTiaoZheng.EndTotalPrice +
        FSuoPeiJinE.EndTotalPrice + FLinShiYongDi.EndTotalPrice + FBaoXianFei.EndTotalPrice;
    FZongJi.PreTotalPrice := FHeJi.PreTotalPrice + FJiaGeTiaoZheng.PreTotalPrice +
        FSuoPeiJinE.PreTotalPrice + FLinShiYongDi.PreTotalPrice + FBaoXianFei.PreTotalPrice;
  end;

begin
  CalculateHeJi;
  CalculateZongJi;
end;

constructor TDealPayControl.Create;
begin
  FPreCalc := TPayNode.Create('小计');
  FTiaoPeiJin := TPayNode.Create('调配金');
  FHeJi := TPayNode.Create('合计');
  FJiaGeTiaoZheng := TPayNode.Create('价格调整');
  FSuoPeiJinE := TPayNode.Create('索赔金额');
  FLinShiYongDi := TPayNode.Create('临时用地');
  FBaoXianFei := TPayNode.Create('保险费');
  FZongJi := TPayNode.Create('总计');
  FOtherPays := TList.Create;
  FZhiFu := TPayNode.Create('支付');
end;

destructor TDealPayControl.Destroy;
begin
  FZhiFu.Free;
  ClearObjects(FOtherPays);
  FOtherPays.Free;
  FZongJi.Free;
  FBaoXianFei.Free;
  FLinShiYongDi.Free;
  FSuoPeiJinE.Free;
  FJiaGeTiaoZheng.Free;
  FHeJi.Free;
  FTiaoPeiJin.Free;
  FPreCalc.Free;
  inherited;
end;

function TDealPayControl.FindOtherPayNode(const AName: string): TPayNode;
var
  i: Integer;
  vPayNode: TPayNode;
begin
  Result := nil;
  for i := 0 to FOtherPays.Count - 1 do
  begin
    vPayNode := TPayNode(FOtherPays.Items[i]);
    if (vPayNode.Name = AName) then
    begin
      Result := vPayNode;
      Break;
    end;
  end;
end;

function TDealPayControl.GetOtherPay(AIndex: Integer): TPayNode;
begin
  Result := TPayNode(FOtherPays.Items[AIndex]);
end;

function TDealPayControl.GetOtherPayCount: Integer;
begin
  Result := FOtherPays.Count;
end;

function TDealPayControl.NewOtherPayNode(const AName: string): TPayNode;
begin
  Result := TPayNode.Create(AName);
  FOtherPays.Add(Result);
end;

end.
