unit rmFxBillsCompareDm;

interface

uses
  SysUtils, Classes, DB, DBClient, ProjectData, sdIDTree, MCacheTree;

type
  {------------------------------------
    fctCommon: 常规的分项清单审核比较模式。
    fctG07: 广东标准表-台账07表，在fctCommon的基础上加一行公路基本造价汇总行。
            需求有标明: 只需汇总项目节。此处不做特别处理，根据报表设置中的选项决定。
  ------------------------------------}
  TFxCompareType = (fctCommon, fctG07);

  TrmFxBillsCompareData = class(TDataModule)
    cdsBills: TClientDataSet;
    cdsBillsCode: TStringField;
    cdsBillsB_Code: TStringField;
    cdsBillsName: TWideStringField;
    cdsBillsUnits: TWideStringField;
    cdsBillsSQuantity: TFloatField;
    cdsBillsSPrice: TFloatField;
    cdsBillsSTotalPrice: TFloatField;
    cdsBillsCQuantity: TFloatField;
    cdsBillsCPrice: TFloatField;
    cdsBillsCTotalPrice: TFloatField;
    cdsBillsDQuantity: TFloatField;
    cdsBillsDPrice: TFloatField;
    cdsBillsDTotalPrice: TFloatField;
    cdsBillsMemoStr: TStringField;
    cdsBillsSDgnQuantity1: TFloatField;
    cdsBillsSDgnQuantity2: TFloatField;
    cdsBillsSDgnQuantity: TStringField;
    cdsBillsCDgnQuantity1: TFloatField;
    cdsBillsCDgnQuantity2: TFloatField;
    cdsBillsCDgnQuantity: TStringField;
    cdsBillsDDgnQuantity1: TFloatField;
    cdsBillsDDgnQuantity2: TFloatField;
    cdsBillsDDgnQuantity: TStringField;
    cdsBillsXiangCode: TWideStringField;
    cdsBillsMuCode: TStringField;
    cdsBillsJieCode: TStringField;
    cdsBillsXiMuCode: TStringField;
  private
    FCacheTree: TReportCacheTree;
    FCompareType: TFxCompareType;

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

    function FilterBillsNode(ANode: TsdIDTreeNode; AParent: TReportCacheNode;
      AIsSource: Boolean): TReportCacheNode;
    procedure FilterBills(ANode: TsdIDTreeNode; AParent: TReportCacheNode;
      AIsSource: Boolean);

    procedure WriteNode(ANode: TReportCacheNode);
    procedure WriteGatherNodeData(const AName: string);
    procedure WriteBills;
  public
    function AssignData(ASProjectData, ACProjectData: TProjectData): TDataSet;

    property CompareType: TFxCompareType read FCompareType write FCompareType;
  end;

implementation

uses
  CacheTree, Globals;

{$R *.dfm}

{ TrmFxBillsCompareData }

function TrmFxBillsCompareData.AssignData(ASProjectData,
  ACProjectData: TProjectData): TDataSet;
begin
  cdsBills.DisableControls;
  cdsBills.Active := True;
  cdsBills.EmptyDataSet;
  FCacheTree := TReportCacheTree.Create(2);
  try
    FilterBills(ASProjectData.BillsCompileData.BillsCompileTree.FirstNode, nil, True);
    FilterBills(ACProjectData.BillsCompileData.BillsCompileTree.FirstNode, nil, False);
    if CompareType = fctG07 then
      FCacheTree.ReCalcGatherData;
    WriteBills;
    Result := cdsBills;
  finally
    FCacheTree.Free;
    cdsBills.EnableControls;
  end;
end;

procedure TrmFxBillsCompareData.FilterBills(ANode: TsdIDTreeNode;
  AParent: TReportCacheNode; AIsSource: Boolean);
var
  ACur: TReportCacheNode;
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;
  ACur := FilterBillsNode(ANode, AParent, AIsSource);
  FilterBills(ANode.FirstChild, ACur, AIsSource);
  FilterBills(ANode.NextSibling, AParent, AIsSource);
end;

function TrmFxBillsCompareData.FilterBillsNode(ANode: TsdIDTreeNode;
  AParent: TReportCacheNode; AIsSource: Boolean): TReportCacheNode;
var
  iGatherCompare: Integer;
  ANextSibling: TReportCacheNode;
begin
  with ANode.Rec do
  begin
    if ANode.Rec.ValueByName('B_Code').AsString <> '' then
      iGatherCompare := ReportConfig.GclCompare
    else
      iGatherCompare := ReportConfig.XmjCompare;
    case iGatherCompare of
      // 按编号
      0: if (ValueByName('Code').asString <> '') or (ValueByName('B_Code').asString <> '') then
           Result := FCacheTree.FindNode(AParent,
               ValueByName('Code').AsString, ValueByName('B_Code').AsString)
         else
           Result := FCacheTree.FindNode(AParent, ValueByName('Code').AsString,
             ValueByName('B_Code').AsString, ValueByName('Name').AsString);
      // 按名称
      1: Result := FCacheTree.FindNode(AParent, ValueByName('Name').AsString);
      // 按编号+名称
      2: Result := FCacheTree.FindNode(AParent, ValueByName('Code').AsString,
             ValueByName('B_Code').AsString, ValueByName('Name').AsString);
    end;

    if not Assigned(Result) then
    begin
      ANextSibling := FCacheTree.FindNextSibling(AParent,
          ValueByName('Code').AsString, ValueByName('B_Code').AsString);
      Result := FCacheTree.AddNode(AParent, ANextSibling);
      Result.Code := ValueByName('Code').AsString;
      Result.B_Code := ValueByName('B_Code').AsString;
      Result.Name := ValueByName('Name').AsString;
      Result.Units := ValueByName('Units').AsString;
    end;
    
    if AIsSource then
    begin
      Result.P_Quantity[0] := ValueByName('Quantity').AsFloat;
      Result.P_Price[0] := ValueByName('Price').AsFloat;
      Result.P_TotalPrice[0] := ValueByName('TotalPrice').AsFloat;

      Result.P_DgnQuantity1[0] := ValueByName('DgnQuantity1').AsFloat;
      Result.P_DgnQuantity2[0] := ValueByName('DgnQuantity2').AsFloat;
    end
    else
    begin
      Result.P_Quantity[1] := ValueByName('Quantity').AsFloat;
      Result.P_Price[1] := ValueByName('Price').AsFloat;
      Result.P_TotalPrice[1] := ValueByName('TotalPrice').AsFloat;

      Result.P_DgnQuantity1[1] := ValueByName('DgnQuantity1').AsFloat;
      Result.P_DgnQuantity2[1] := ValueByName('DgnQuantity2').AsFloat;
    end;
  end;
end;

function TrmFxBillsCompareData.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 TrmFxBillsCompareData.WriteBills;
begin
  WriteNode(TReportCacheNode(FCacheTree.FirstNode));
  WriteGatherNodeData('公路基本造价');
end;

procedure TrmFxBillsCompareData.WriteGatherNodeData(const AName: string);
begin
  cdsBills.Append;
  cdsBillsName.AsString := AName;
  with FCacheTree.GatherCacheNode do
  begin
    cdsBillsSTotalPrice.AsFloat := P_TotalPrice[0];
    cdsBillsCTotalPrice.AsFloat := P_TotalPrice[1];
    cdsBillsDTotalPrice.AsFloat := P_TotalPrice[1] - P_TotalPrice[0];
  end;
  cdsBills.Post;
end;

procedure TrmFxBillsCompareData.WriteNode(ANode: TReportCacheNode);
begin
  if not Assigned(ANode) then Exit;

  cdsBills.Append;
  cdsBillsCode.AsString := ANode.Code;
  cdsBillsB_Code.AsString := ANode.B_Code;
  cdsBillsName.AsString := ANode.Name;
  cdsBillsUnits.AsString := ANode.Units;

  cdsBillsSQuantity.AsFloat := ANode.P_Quantity[0];
  cdsBillsSPrice.AsFloat := ANode.P_Price[0];
  cdsBillsSTotalPrice.AsFloat := ANode.P_TotalPrice[0];
  cdsBillsSDgnQuantity1.AsFloat := ANode.P_DgnQuantity1[0];
  cdsBillsSDgnQuantity2.AsFloat := ANode.P_DgnQuantity2[0];
  cdsBillsSDgnQuantity.AsString := GetDgnQuantity(cdsBillsSDgnQuantity1.AsFloat,
      cdsBillsSDgnQuantity2.AsFloat);

  cdsBillsCQuantity.AsFloat := ANode.P_Quantity[1];
  cdsBillsCPrice.AsFloat := ANode.P_Price[1];
  cdsBillsCTotalPrice.AsFloat := ANode.P_TotalPrice[1];
  cdsBillsCDgnQuantity1.AsFloat := ANode.P_DgnQuantity1[1];
  cdsBillsCDgnQuantity2.AsFloat := ANode.P_DgnQuantity2[1];
  cdsBillsCDgnQuantity.AsString := GetDgnQuantity(cdsBillsCDgnQuantity1.AsFloat,
      cdsBillsCDgnQuantity2.AsFloat);

  cdsBillsDQuantity.AsFloat := ANode.P_Quantity[1] - ANode.P_Quantity[0];
  cdsBillsDPrice.AsFloat := ANode.P_Price[1] - ANode.P_Price[0];
  cdsBillsDTotalPrice.AsFloat := ANode.P_TotalPrice[1] - ANode.P_TotalPrice[0];
  cdsBillsDDgnQuantity1.AsFloat := ANode.P_DgnQuantity1[1] - ANode.P_DgnQuantity1[0];
  cdsBillsDDgnQuantity2.AsFloat := ANode.P_DgnQuantity2[1] - ANode.P_DgnQuantity2[0];
  cdsBillsDDgnQuantity.AsString := GetDgnQuantity(cdsBillsDDgnQuantity1.AsFloat,
      cdsBillsDDgnQuantity2.AsFloat);

  cdsBillsXiangCode.AsString := ANode.XiangCode;
  cdsBillsMuCode.AsString := ANode.MuCode;
  cdsBillsJieCode.AsString := ANode.JieCode;
  cdsBillsXiMuCode.AsString := ANode.XiMuCode;
  cdsBills.Post;

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

end.
