unit rmBillsPhaseGatherDm;

interface

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

type
  TrmBillsPhaseGatherData = class(TDataModule)
    cdsZjtzBills: TClientDataSet;
    cdsZjtzBillsID: TIntegerField;
    cdsZjtzBillsParentID: TIntegerField;
    cdsZjtzBillsNextSiblingID: TIntegerField;
    cdsZjtzBillsCode: TWideStringField;
    cdsZjtzBillsName: TWideStringField;
    cdsZjtzBillsUnits: TWideStringField;
    cdsZjtzBillscbDgnQty1: TFloatField;
    cdsZjtzBillscbDgnQty2: TFloatField;
    cdsZjtzBillscbDgnQty: TStringField;
    cdsZjtzBillscbTotalPrice: TFloatField;
    cdsZjtzBillssscDgnQty1: TFloatField;
    cdsZjtzBillssscDgnQty2: TFloatField;
    cdsZjtzBillssscDgnQty: TStringField;
    cdsZjtzBillssscTotalPrice: TFloatField;
    cdsZjtzBillsshtDgnQty1: TFloatField;
    cdsZjtzBillsshtDgnQty2: TFloatField;
    cdsZjtzBillsshtDgnQty: TStringField;
    cdsZjtzBillsshtTotalPrice: TFloatField;
    cdsZjtzBillshtDgnQty1: TFloatField;
    cdsZjtzBillshtDgnQty2: TFloatField;
    cdsZjtzBillshtDgnQty: TStringField;
    cdsZjtzBillsTotalPrice: TFloatField;
    cdsZjtzBillsbgDgnQty1: TFloatField;
    cdsZjtzBillsbgDgnQty2: TFloatField;
    cdsZjtzBillsbgDgnQty: TStringField;
    cdsZjtzBillsEndQcTotalPrice: TFloatField;
    cdsZjtzBillsEndDealTotalPrice: TFloatField;
    cdsZjtzBillsMemoStr: TWideStringField;
    cdsZjtzBillssumDgnQty1: TFloatField;
    cdsZjtzBillssumDgnQty2: TFloatField;
    cdsZjtzBillssumDgnQty: TStringField;
    cdsZjtzBillsDgnQty1: TFloatField;
    cdsZjtzBillsDgnQty2: TFloatField;
    cdsZjtzBillsDgnQty: TStringField;
    cdsZjtzBillsDgnQtyA1: TFloatField;
    cdsZjtzBillsDgnQtyA2: TFloatField;
    cdsZjtzBillsDgnQtyA: TStringField;
  private
    FCacheTree: TSpecPhaseCacheTree;
    FProjectData: TProjectData;

    function GetDgnQuantity(ANum1, ANum2: Double): string;

    procedure BeforeGather;
    procedure AfterGather;

    procedure OpenProject(AProject: TSelectProject);
    procedure FreeProject;

    function AddBillsNode(ANode: TBillsIDTreeNode;
      AParent: TSpecPhaseCacheNode): TSpecPhaseCacheNode;

    function AddSpecBillsNode(ANode: TsdIDTreeNode; AParent: TSpecPhaseCacheNode;
      ASelectProject: TSelectProject): TSpecPhaseCacheNode;
    function AddSpecBills(ANode: TsdIDTreeNode; AParent: TSpecPhaseCacheNode;
      ASelectProject: TSelectProject): TSpecPhaseCacheNode;

    function AddPhaseBillsNode(ANode: TsdIDTreeNode;
      AParent: TSpecPhaseCacheNode): TSpecPhaseCacheNode;
    function AddPhaseBills(ANode: TsdIDTreeNode;
      AParent: TSpecPhaseCacheNode): TSpecPhaseCacheNode;

    procedure GatherProject(AProject: TSelectProject);

    procedure WriteNode(ANode: TSpecPhaseCacheNode);
    procedure WriteData;
  public
    function AssignData(AProjects: TList): TDataSet;
  end;

implementation

uses CacheTree, Globals, UtilMethods;

{$R *.dfm}

{ TrmBillsPhaseGatherData }

function TrmBillsPhaseGatherData.AddBillsNode(ANode: TBillsIDTreeNode;
  AParent: TSpecPhaseCacheNode): TSpecPhaseCacheNode;
var
  Rec: TBillsRecord;
  iGatherCompare: Integer;
  ANextSibling: TSpecPhaseCacheNode;
begin
  Rec := ANode.Rec;

  if Rec.B_Code.AsString <> '' then
    iGatherCompare := ReportConfig.GclCompare
  else
    iGatherCompare := ReportConfig.XmjCompare;
  case iGatherCompare of
    // 按编号
    0: if (Rec.Code.asString <> '') or (Rec.B_Code.asString <> '') then
         Result := FCacheTree.FindNode(AParent, Rec.Code.AsString, Rec.B_Code.AsString)
       else
         Result := FCacheTree.FindNode(AParent, Rec.Name.AsString);
    // 按名称
    1: Result := FCacheTree.FindNode(AParent, Rec.Name.AsString);
    // 按编号+名称
    2: Result := FCacheTree.FindNode(AParent, Rec.Code.AsString,
           Rec.B_Code.AsString, Rec.Name.AsString);
  end;

  if not Assigned(Result) then
  begin
    ANextSibling := FCacheTree.FindNextSibling(AParent,
        Rec.Code.AsString, Rec.B_Code.AsString);
    Result := FCacheTree.AddNode(AParent, ANextSibling);
    Result.Code := Rec.Code.AsString;
    Result.B_Code := Rec.B_Code.AsString;
    Result.Name := Rec.Name.AsString;
    Result.Units := Rec.Units.AsString;
  end;
end;

function TrmBillsPhaseGatherData.AddPhaseBills(ANode: TsdIDTreeNode;
  AParent: TSpecPhaseCacheNode): TSpecPhaseCacheNode;
begin
  if not Assigned(ANode) then Exit;
  // 按设置的层次汇总(Level从0开始取值)
  case ReportConfig.GatherLevel of
    // 项
    0: if ANode.Level > 1 then Exit;
    // 目
    1: if ANode.Level > 2 then Exit;
    // 节
    2: if ANode.Level > 3 then Exit;
    // 细目
    3: if ANode.Level > 4 then Exit;
    // 项目节
    4: if ANode.Rec.ValueByName('B_Code').AsString <> '' then Exit;
  end;
  if ANode.Rec.ValueByName('B_Code').AsString <> '' then Exit;
  Result := AddPhaseBillsNode(ANode, AParent);
  AddPhaseBills(ANode.FirstChild, Result);
  AddPhaseBills(ANode.NextSibling, AParent);
end;

function TrmBillsPhaseGatherData.AddPhaseBillsNode(ANode: TsdIDTreeNode;
  AParent: TSpecPhaseCacheNode): TSpecPhaseCacheNode;
var
  vNode: TMeasureBillsIDTreeNode;
  Rec: TBillsRecord;
  StageRec: TStageRecord;
begin
  vNode :=  TMeasureBillsIDTreeNode(ANode);
  Result := AddBillsNode(vNode, AParent);
  Rec := vNode.Rec;
  Result.DgnQty1 := Result.DgnQty1 + Rec.DgnQuantity1.AsFloat;
  Result.DgnQty2 := Result.DgnQty2 + Rec.DgnQuantity2.AsFloat;
  Result.TotalPrice := Result.TotalPrice + Rec.TotalPrice.AsFloat;

  Result.htDgnQty1 := Result.htDgnQty1 + Rec.DealDgnQuantity1.AsFloat;
  Result.htDgnQty2 := Result.htDgnQty2 + Rec.DealDgnQuantity2.AsFloat;
  Result.bgDgnQty1 := Result.bgDgnQty1 + Rec.CDgnQuantity1.AsFloat;
  Result.bgDgnQty2 := Result.bgDgnQty2 + Rec.CDgnQuantity2.AsFloat;

  StageRec := vNode.StageRec;
  if Assigned(StageRec) then
  begin
    Result.EndDealTotalPrice := Result.EndDealTotalPrice + StageRec.EndDealTotalPrice.AsFloat;
    Result.EndQcTotalPrice := Result.EndQcTotalPrice + StageRec.EndQcTotalPrice.AsFloat;
  end;
end;

function TrmBillsPhaseGatherData.AddSpecBills(ANode: TsdIDTreeNode;
  AParent: TSpecPhaseCacheNode; ASelectProject: TSelectProject): TSpecPhaseCacheNode;
begin
  if not Assigned(ANode) then Exit;
  // 按设置的层次汇总(Level从0开始取值)
  case ReportConfig.GatherLevel of
    // 项
    0: if ANode.Level > 1 then Exit;
    // 目
    1: if ANode.Level > 2 then Exit;
    // 节
    2: if ANode.Level > 3 then Exit;
    // 细目
    3: if ANode.Level > 4 then Exit;
    // 项目节
    4: if ANode.Rec.ValueByName('B_Code').AsString <> '' then Exit;
  end;
  if ANode.Rec.ValueByName('B_Code').AsString <> '' then Exit;

  Result := AddSpecBillsNode(ANode, AParent, ASelectProject);
  AddSpecBills(ANode.FirstChild, Result, ASelectProject);
  AddSpecBills(ANode.NextSibling, AParent, ASelectProject);
end;

function TrmBillsPhaseGatherData.AddSpecBillsNode(ANode: TsdIDTreeNode;
  AParent: TSpecPhaseCacheNode;
  ASelectProject: TSelectProject): TSpecPhaseCacheNode;
var
  vNode: TBillsIDTreeNode;
  Rec: TBillsRecord;
begin
  vNode := TBillsIDTreeNode(ANode);
  Result := AddBillsNode(vNode, AParent);

  Rec := vNode.Rec;
  if ASelectProject.IsPD then
  begin
    Result.cbDgnQty1 := Rec.DgnQuantity1.AsFloat;
    Result.cbDgnQty2 := Rec.DgnQuantity2.AsFloat;
    Result.cbTotalPrice := Rec.TotalPrice.AsFloat;
  end
  else if ASelectProject.IsCddSc then
  begin
    Result.sscDgnQty1 := Rec.DgnQuantity1.AsFloat;
    Result.sscDgnQty2 := Rec.DgnQuantity2.AsFloat;
    Result.sscTotalPrice := Rec.TotalPrice.AsFloat;
  end
  else if ASelectProject.IsCddHt then
  begin
    Result.shtDgnQty1 := Rec.DgnQuantity1.AsFloat;
    Result.shtDgnQty2 := Rec.DgnQuantity2.AsFloat;
    Result.shtTotalPrice := Rec.TotalPrice.AsFloat;
  end;
end;

procedure TrmBillsPhaseGatherData.AfterGather;
begin
  cdsZjtzBills.EnableControls;

  FCacheTree.Free;
end;

function TrmBillsPhaseGatherData.AssignData(AProjects: TList): TDataSet;
var
  iProject: Integer;
begin
  BeforeGather;
  try
    for iProject := 0 to AProjects.Count - 1 do
      GatherProject(AProjects[iProject]);
    WriteData;
  finally
    Result := cdsZjtzBills;
    AfterGather;
  end;
end;

procedure TrmBillsPhaseGatherData.BeforeGather;
begin
  FCacheTree := TSpecPhaseCacheTree.Create;

  cdsZjtzBills.DisableControls;
  cdsZjtzBills.Active := True;
  cdsZjtzBills.EmptyDataSet;
end;

procedure TrmBillsPhaseGatherData.FreeProject;
begin
  if not Assigned(OpenProjectManager.FindProjectData(FProjectData.ProjectID)) then
    FProjectData.Free;
end;

procedure TrmBillsPhaseGatherData.GatherProject(AProject: TSelectProject);
begin
  OpenProject(AProject);
  try
    if AProject.IsPD or AProject.IsCddSc or AProject.IsCddHt then
      AddSpecBills(FProjectData.BillsCompileData.BillsCompileTree.FirstNode, nil, AProject)
    else
      AddPhaseBills(FProjectData.BillsMeasureData.BillsMeasureTree.FirstNode, nil);
  finally
    FreeProject;
  end;
end;

function TrmBillsPhaseGatherData.GetDgnQuantity(ANum1,
  ANum2: Double): string;
begin
  Result := '';
  if ANum1 <> 0 then
  begin
    Result := FloatToStr(ANum1);
    if ANum2 <> 0 then
      Result := Result + '/' + FloatToStr(ANum2);
  end;
end;

procedure TrmBillsPhaseGatherData.OpenProject(AProject: TSelectProject);
var
  Rec: TsdDataRecord;
begin
  FProjectData := OpenProjectManager.FindProjectData(AProject.ProjectID);
  if not Assigned(FProjectData) then
  begin
    Rec := ProjectManager.sddProjectsInfo.FindKey('idxID', AProject.ProjectID);
    FProjectData := TProjectData.Create;
    if AProject.IsPD or AProject.IsCddSc or AProject.IsCddHt then
      FProjectData.OpenForReport(GetMyProjectsFilePath + Rec.ValueByName('FileName').AsString)
    else
      FProjectData.OpenForReport3(GetMyProjectsFilePath + Rec.ValueByName('FileName').AsString);
  end;
end;

procedure TrmBillsPhaseGatherData.WriteData;
begin
  WriteNode(TSpecPhaseCacheNode(FCacheTree.FirstNode));
end;

procedure TrmBillsPhaseGatherData.WriteNode(ANode: TSpecPhaseCacheNode);
begin
  if not Assigned(ANode) then Exit;

  cdsZjtzBills.Append;
  cdsZjtzBillsID.AsInteger := ANode.ID;
  cdsZjtzBillsParentID.AsInteger := ANode.ParentID;
  cdsZjtzBillsNextSiblingID.AsInteger := ANode.NextSiblingID;

  cdsZjtzBillsCode.AsString := ANode.Code;
  cdsZjtzBillsName.AsString := ANode.Name;
  cdsZjtzBillsUnits.AsString := ANode.Units;

  cdsZjtzBillscbDgnQty1.AsFloat := ANode.cbDgnQty1;
  cdsZjtzBillscbDgnQty2.AsFloat := ANode.cbDgnQty2;
  cdsZjtzBillscbDgnQty.AsString := GetDgnQuantity(ANode.cbDgnQty1, ANode.cbDgnQty2);
  cdsZjtzBillscbTotalPrice.AsFloat := ANode.cbTotalPrice;

  cdsZjtzBillssscDgnQty1.AsFloat := ANode.sscDgnQty1;
  cdsZjtzBillssscDgnQty2.AsFloat := ANode.sscDgnQty2;
  cdsZjtzBillssscDgnQty.AsString := GetDgnQuantity(ANode.sscDgnQty1, ANode.sscDgnQty2);
  cdsZjtzBillssscTotalPrice.AsFloat := ANode.sscTotalPrice;

  cdsZjtzBillsshtDgnQty1.AsFloat := ANode.shtDgnQty1;
  cdsZjtzBillsshtDgnQty2.AsFloat := ANode.shtDgnQty2;
  cdsZjtzBillsshtDgnQty.AsString := GetDgnQuantity(ANode.shtDgnQty1, ANode.shtDgnQty2);
  cdsZjtzBillsshtTotalPrice.AsFloat := ANode.shtTotalPrice;

  cdsZjtzBillsDgnQty1.AsFloat := ANode.DgnQty1;
  cdsZjtzBillsDgnQty2.AsFloat := ANode.DgnQty2;
  cdsZjtzBillsDgnQty.AsString := GetDgnQuantity(ANode.DgnQty1, ANode.DgnQty2);
  cdsZjtzBillsTotalPrice.AsFloat := ANode.TotalPrice;

  cdsZjtzBillshtDgnQty1.AsFloat := ANode.htDgnQty1;
  cdsZjtzBillshtDgnQty2.AsFloat := ANode.htDgnQty2;
  cdsZjtzBillshtDgnQty.AsString := GetDgnQuantity(ANode.htDgnQty1, ANode.htDgnQty2);
  cdsZjtzBillsbgDgnQty1.AsFloat := ANode.bgDgnQty1;
  cdsZjtzBillsbgDgnQty2.AsFloat := ANode.bgDgnQty2;
  cdsZjtzBillsbgDgnQty.AsString := GetDgnQuantity(ANode.bgDgnQty1, ANode.bgDgnQty2);
  cdsZjtzBillsEndQcTotalPrice.AsFloat := ANode.EndQcTotalPrice;
  cdsZjtzBillsEndDealTotalPrice.AsFloat := ANode.EndDealTotalPrice;

  cdsZjtzBillssumDgnQty1.AsFloat := ANode.htDgnQty1 + ANode.bgDgnQty1;
  cdsZjtzBillssumDgnQty2.AsFloat := ANode.htDgnQty2 + ANode.bgDgnQty2;
  cdsZjtzBillssumDgnQty.AsString := GetDgnQuantity(cdsZjtzBillssumDgnQty1.AsFloat, cdsZjtzBillssumDgnQty2.AsFloat);

  cdsZjtzBillsDgnQtyA1.AsFloat := ANode.DgnQty1 + ANode.bgDgnQty1;
  cdsZjtzBillsDgnQtyA2.AsFloat := ANode.DgnQty2 + ANode.bgDgnQty2;
  cdsZjtzBillsDgnQtyA.AsString := GetDgnQuantity(cdsZjtzBillsDgnQtyA1.AsFloat, cdsZjtzBillsDgnQtyA2.AsFloat);
  cdsZjtzBills.Post;

  WriteNode(TSpecPhaseCacheNode(ANode.FirstChild));
  WriteNode(TSpecPhaseCacheNode(ANode.NextSibling));
end;

end.
