unit rmWeiWuZjjlGatherDm;

interface

uses
  SysUtils, Classes, ProjectData, DB, sdDB, DBClient, sdIDTree, BillsTree;

type
  TZjjl = class
  private
    FCode: string;
    FCertificateCode: string;
    FBGLCode: string;
    FPegName: string;
    FBeginPeg: string;
    FEndPeg: string;
    FFBFXName: string;
    FUnitName: string;
    FDrawingCode: string;
    FFormulaMemo: string;
    FRelaFile: string;

    FBillsCode: string;
    FBillsName: string;
    FBillsUnits: string;
    FBillsPrice: Double;
    FFilterDrawingCode: string;

    FBillsCurDealQuantity: Double;
    FBillsCurDealTotalPrice: Double;
    FBillsCurQcQuantity: Double;
    FBillsCurQcTotalPrice: Double;
    FBillsCurGatherQuantity: Double;
    FBillsCurGatherTotalPrice: Double;
    FBillsEndDealQuantity: Double;
    FBillsEndDealTotalPrice: Double;
    FBillsEndQcQuantity: Double;
    FBillsEndQcTotalPrice: Double;
    FBillsEndGatherQuantity: Double;
    FBillsEndGatherTotalPrice: Double;

    FBillsOrgQuantity: Double;
    FBillsOrgTotalPrice: Double;
    FBillsMisQuantity: Double;
    FBillsMisTotalPrice: Double;
    FBillsOthQuantity: Double;
    FBillsOthTotalPrice: Double;
    FBillsQuantity: Double;
    FBillsTotalPrice: Double;

    FFenBuName: string;
    FDanWeiName: string;

    FIndexCode: string;
    FSerialNo: Integer;

    function MergeStr(AStr1, AStr2: string): string;
  public
    constructor Create(ARec, AStageRec: TsdDataRecord; ANode: TBillsIDTreeNode);

    procedure Merge(ARec, AStageRec: TsdDataRecord; ANode: TBillsIDTreeNode);
  end;

  TrmWeiWuZjjlGatherData = class(TDataModule)
    cdsZjjl: TClientDataSet;
    cdsZjjlCode: TWideStringField;
    cdsZjjlCertificateCode: TWideStringField;
    cdsZjjlBGLCode: TMemoField;
    cdsZjjlPegName: TWideStringField;
    cdsZjjlBeginPeg: TWideStringField;
    cdsZjjlEndPeg: TWideStringField;
    cdsZjjlFBFXName: TWideStringField;
    cdsZjjlUnitName: TWideStringField;
    cdsZjjlDrawingCode: TWideStringField;
    cdsZjjlFormulaMemo: TMemoField;
    cdsZjjlRelaFile: TMemoField;
    cdsZjjlBillsCode: TStringField;
    cdsZjjlBillsName: TWideStringField;
    cdsZjjlBillsUnits: TWideStringField;
    cdsZjjlBillsPrice: TFloatField;
    cdsZjjlFilterDrawingCode: TWideStringField;
    cdsZjjlBillsCurDealQuantity: TFloatField;
    cdsZjjlBillsCurDealTotalPrice: TFloatField;
    cdsZjjlBillsCurQcQuantity: TFloatField;
    cdsZjjlBillsCurQcTotalPrice: TFloatField;
    cdsZjjlBillsCurGatherQuantity: TFloatField;
    cdsZjjlBillsCurGatherTotalPrice: TFloatField;
    cdsZjjlBillsEndDealQuantity: TFloatField;
    cdsZjjlBillsEndDealTotalPrice: TFloatField;
    cdsZjjlBillsEndQcQuantity: TFloatField;
    cdsZjjlBillsEndQcTotalPrice: TFloatField;
    cdsZjjlBillsEndGatherQuantity: TFloatField;
    cdsZjjlBillsEndGatherTotalPrice: TFloatField;
    cdsZjjlBillsOrgQuantity: TFloatField;
    cdsZjjlBillsOrgTotalPrice: TFloatField;
    cdsZjjlBillsMisQuantity: TFloatField;
    cdsZjjlBillsMisTotalPrice: TFloatField;
    cdsZjjlBillsOthQuantity: TFloatField;
    cdsZjjlBillsOthTotalPrice: TFloatField;
    cdsZjjlBillsQuantity: TFloatField;
    cdsZjjlBillsTotalPrice: TFloatField;
    cdsZjjlFenBuName: TWideStringField;
    cdsZjjlDanWeiName: TWideStringField;
    cdsZjjlProjectName: TWideStringField;
    cdsZjjlDealCode: TWideStringField;
    cdsZjjlCName: TWideStringField;
    cdsZjjlSName: TWideStringField;
    cdsZjjlPhaseIndex: TWideStringField;
    cdsZjjlDealName: TWideStringField;
    cdsZjjlFlowIndex: TIntegerField;
  private
    FZjjlList: TList;
    FPreText: string;
    FPhaseIndex: Integer;
    function FindZjjl(ARec: TsdDataRecord; ANode: TBillsIDTreeNode): TZjjl;

    procedure GatherZjjl(AProjectData: TProjectData);
    procedure WriteData(AProjectData: TProjectData);
  public
    function AssignData(AProjectData: TProjectData): TDataSet;
  end;

implementation

uses
  ZhAPI, PhaseData, UtilMethods, BillsMeasureDm;

{$R *.dfm}

function GetThirdPartString(const AStr: string; AFilter: Char = '-'): string;
var
  sgs: TStringList;
begin
  sgs := TStringList.Create;
  try
    sgs.Delimiter := AFilter;
    sgs.DelimitedText := AStr;

    while sgs.Count > 3 do
      sgs.Delete(sgs.Count - 1);
    Result := sgs.DelimitedText;
  finally
    sgs.Free;
  end;
end;

function GetLeafXmj(ANode: TBillsIDTreeNode): TBillsIDTreeNode;
begin
  Result := ANode;
  while Assigned(Result) and (Result.Rec.B_Code.AsString <> '') do
    Result := TBillsIDTreeNode(Result.Parent);
end;

function GetLeafXmjDrawingCode(ANode: TBillsIDTreeNode): String;
var
  vLeafXmj: TsdIDTreeNode;
begin
  Result := '';
  vLeafXmj := GetLeafXmj(ANode);
  if Assigned(vLeafXmj) then
    Result := vLeafXmj.Rec.ValueByName('DrawingCode').AsString;
end;

{ TZjjl }

constructor TZjjl.Create(ARec, AStageRec: TsdDataRecord; ANode: TBillsIDTreeNode);

  // 取树结构的第ALevel层节点的名称（level从0开始）
  function GetNameByLevel(ANode: TBillsIDTreeNode; ALevel: Integer): string;
  begin
    Result := '';
    if not Assigned(ANode) then Exit;
    if ANode.Level = ALevel then
      Result := ANode.Rec.Name.AsString
    else if ANode.Level > ALevel then
      Result := GetNameByLevel(TBillsIDTreeNode(ANode.Parent), ALevel);
  end;

  function GetNameDanWei(ANode: TBillsIDTreeNode): string;
  begin
    // 取树结构的第二层节点的名称
    Result := GetNameByLevel(ANode, 1);
  end;

  // ANode为计量单元节点，APegNode为桩号节点
  function GetNameFenBu(ANode, APegNode: TBillsIDTreeNode): string;
  var
    vCurNode: TBillsIDTreeNode;
  begin
    // 如果计量单元节点的名称为桩号（转化为判断计量单元节点与桩号节点为同一个）
    if not Assigned(APegNode) or (ANode.ID = APegNode.ID) then
      // 取树结构的第三层节点的名称
      Result := GetNameByLevel(ANode, 2)
    // 否则，取桩号节点的子节点的名称
    else
    begin
      vCurNode := ANode;
      while vCurNode.Level > APegNode.Level + 1 do
        vCurNode := TBillsIDTreeNode(vCurNode.Parent);
      Result := vCurNode.Rec.Name.AsString;
    end;
  end;

  function GetPegNode(ANode: TBillsIDTreeNode): TBillsIDTreeNode;
  begin
    Result := nil;
    if not Assigned(ANode) then Exit;
    if CheckPeg(ANode.Rec.Name.AsString) then
      Result := ANode
    else
      Result := GetPegNode(TBillsIDTreeNode(ANode.Parent));
  end;

var
  vLeafXmj, vPegNode: TBillsIDTreeNode;
begin
  FCode := ARec.ValueByName('Code').AsString;
  FCertificateCode := ARec.ValueByName('CertificateCode').AsString;
  FBGLCode := ARec.ValueByName('BGLCode').AsString;
  FPegName := ARec.ValueByName('PegName').AsString;
  FBeginPeg := ARec.ValueByName('BeginPeg').AsString;
  FEndPeg := ARec.ValueByName('EndPeg').AsString;
  FFBFXName := ARec.ValueByName('FBFXName').AsString;
  FUnitName := ARec.ValueByName('UnitName').AsString;
  FDrawingCode := ARec.ValueByName('DrawingCode').AsString;
  FFormulaMemo := ARec.ValueByName('FormulaMemo').AsString;
  FRelaFile := ARec.ValueByName('RelaFile').AsString;

  FBillsCode := ANode.Rec.ValueByName('B_Code').AsString;
  FBillsName := ANode.Rec.ValueByName('Name').AsString;
  FBillsUnits := ANode.Rec.ValueByName('Units').AsString;
  FBillsPrice := ANode.Rec.ValueByName('Price').AsFloat;
  FFilterDrawingCode := GetThirdPartString(GetLeafXmjDrawingCode(ANode));

  if Assigned(AStageRec) then
  begin
    FBillsCurDealQuantity := AStageRec.ValueByName('DealQuantity').AsFloat;
    FBillsCurDealTotalPrice := AStageRec.ValueByName('DealTotalPrice').AsFloat;
    FBillsCurQcQuantity := AStageRec.ValueByName('QcQuantity').AsFloat;
    FBillsCurQcTotalPrice := AStageRec.ValueByName('QcTotalPrice').AsFloat;
    FBillsCurGatherQuantity := AStageRec.ValueByName('GatherQuantity').AsFloat;
    FBillsCurGatherTotalPrice := AStageRec.ValueByName('GatherTotalPrice').AsFloat;

    FBillsEndDealQuantity := AStageRec.ValueByName('DealQuantity').AsFloat;
    FBillsEndDealTotalPrice := AStageRec.ValueByName('DealTotalPrice').AsFloat;
    FBillsEndQcQuantity := AStageRec.ValueByName('QcQuantity').AsFloat;
    FBillsEndQcTotalPrice := AStageRec.ValueByName('QcTotalPrice').AsFloat;
    FBillsEndGatherQuantity := AStageRec.ValueByName('GatherQuantity').AsFloat;
    FBillsEndGatherTotalPrice := AStageRec.ValueByName('GatherTotalPrice').AsFloat;
  end;

  FBillsOrgQuantity := ANode.Rec.OrgQuantity.AsFloat;
  FBillsOrgTotalPrice := ANode.Rec.OrgTotalPrice.AsFloat;
  FBillsMisQuantity := ANode.Rec.MisQuantity.AsFloat;
  FBillsMisTotalPrice := ANode.Rec.MisTotalPrice.AsFloat;
  FBillsOthQuantity := ANode.Rec.OthQuantity.AsFloat;
  FBillsOthTotalPrice := ANode.Rec.OthTotalPrice.AsFloat;
  FBillsQuantity := ANode.Rec.Quantity.AsFloat;
  FBillsTotalPrice := ANode.Rec.TotalPrice.AsFloat;

  vLeafXmj := GetLeafXmj(ANode);
  vPegNode := GetPegNode(ANode);
  FFenBuName := GetNameFenBu(vLeafXmj, vPegNode);
  FDanWeiName := GetNameDanWei(vLeafXmj);

  FIndexCode := B_CodeToIndexCode(FBillsCode);
  FSerialNo := ANode.MajorIndex;
end;

procedure TZjjl.Merge(ARec, AStageRec: TsdDataRecord; ANode: TBillsIDTreeNode);
begin
  FCertificateCode := MergeStr(FCertificateCode, ARec.ValueByName('CertificateCode').AsString);
  FBGLCode := MergeRelaBGL(FBGLCode, ARec.ValueByName('BGLCode').AsString);
  FDrawingCode := MergeStr(FDrawingCode, ARec.ValueByName('DrawingCode').AsString);
  FFormulaMemo := MergeStr(FFormulaMemo, ARec.ValueByName('FormulaMemo').AsString);
  FRelaFile := MergeStr(FRelaFile, ARec.ValueByName('RelaFile').AsString);

  if Assigned(AStageRec) then
  begin
    FBillsCurDealQuantity := FBillsCurDealQuantity + AStageRec.ValueByName('DealQuantity').AsFloat;
    FBillsCurDealTotalPrice := FBillsCurDealTotalPrice + AStageRec.ValueByName('DealTotalPrice').AsFloat;
    FBillsCurQcQuantity := FBillsCurQcQuantity + AStageRec.ValueByName('QcQuantity').AsFloat;
    FBillsCurQcTotalPrice := FBillsCurQcTotalPrice + AStageRec.ValueByName('QcTotalPrice').AsFloat;
    FBillsCurGatherQuantity := FBillsCurGatherQuantity + AStageRec.ValueByName('GatherQuantity').AsFloat;
    FBillsCurGatherTotalPrice := FBillsCurGatherTotalPrice + AStageRec.ValueByName('GatherTotalPrice').AsFloat;

    FBillsEndDealQuantity := FBillsEndDealQuantity + AStageRec.ValueByName('DealQuantity').AsFloat;
    FBillsEndDealTotalPrice := FBillsEndDealTotalPrice + AStageRec.ValueByName('DealTotalPrice').AsFloat;
    FBillsEndQcQuantity := FBillsEndQcQuantity + AStageRec.ValueByName('QcQuantity').AsFloat;
    FBillsEndQcTotalPrice := FBillsEndQcTotalPrice + AStageRec.ValueByName('QcTotalPrice').AsFloat;
    FBillsEndGatherQuantity := FBillsEndGatherQuantity + AStageRec.ValueByName('GatherQuantity').AsFloat;
    FBillsEndGatherTotalPrice := FBillsEndGatherTotalPrice + AStageRec.ValueByName('GatherTotalPrice').AsFloat;
  end;

  FBillsOrgQuantity := FBillsOrgQuantity + ANode.Rec.OrgQuantity.AsFloat;
  FBillsOrgTotalPrice := FBillsOrgTotalPrice + ANode.Rec.OrgTotalPrice.AsFloat;
  FBillsMisQuantity := FBillsMisQuantity + ANode.Rec.MisQuantity.AsFloat;
  FBillsMisTotalPrice := FBillsMisTotalPrice + ANode.Rec.MisTotalPrice.AsFloat;
  FBillsOthQuantity := FBillsOthQuantity + ANode.Rec.OthQuantity.AsFloat;
  FBillsOthTotalPrice := FBillsOthTotalPrice + ANode.Rec.OthTotalPrice.AsFloat;
  FBillsQuantity := FBillsQuantity + ANode.Rec.Quantity.AsFloat;
  FBillsTotalPrice := FBillsTotalPrice + ANode.Rec.TotalPrice.AsFloat;

  if ANode.MajorIndex < FSerialNo then
    FSerialNo := ANode.MajorIndex;
end;

function TZjjl.MergeStr(AStr1, AStr2: string): string;
begin
  if (AStr1 <> '') then
  begin
    if (AStr2 <> '') then
      Result := AStr1 + ';' + AStr2
    else
      Result := AStr1;
  end
  else
  begin
    if (AStr2 <> '') then
      Result := AStr2
    else
      Result := '';
  end;
end;

{ TrmWeiWuZjjlGatherData }

function TrmWeiWuZjjlGatherData.AssignData(
  AProjectData: TProjectData): TDataSet;

  function IndexCodeCompare(Item1, Item2: Pointer): Integer;
  var
    vZjjl1, vZjjl2: TZjjl;
  begin
    vZjjl1 := TZjjl(Item1);
    vZjjl2 := TZjjl(Item2);
    Result := CompareStr(vZjjl1.FIndexCode, vZjjl2.FIndexCode);
    if Result = 0 then
      Result := vZjjl1.FSerialNo - vZjjl2.FSerialNo;
  end;

begin
  FZjjlList := TList.Create;
  try
    if AProjectData.PhaseData.Active then
    begin
      FPreText := AProjectData.PhaseData.PhaseProperty.ZJJLPreText;
      FPhaseIndex := AProjectData.PhaseIndex;
      GatherZjjl(AProjectData);
      FZjjlList.Sort(@IndexCodeCompare);
      WriteData(AProjectData);
    end;
    Result := cdsZjjl;
  finally
    ClearObjects(FZjjlList);
    FZjjlList.Free;
  end;
end;

function TrmWeiWuZjjlGatherData.FindZjjl(ARec: TsdDataRecord; ANode: TBillsIDTreeNode): TZjjl;
var
  sCode, sName, sUnits, sDrawingCode: string;
  fPrice: Double;
  i: Integer;
  vZ: TZjjl;
begin
  sCode := ANode.Rec.ValueByName('B_Code').AsString;
  sName := ANode.Rec.ValueByName('Name').AsString;
  sUnits := ANode.Rec.ValueByName('Units').AsString;
  sDrawingCode := GetThirdPartString(GetLeafXmjDrawingCode(ANode));
  fPrice := ANode.Rec.valueByName('Price').AsFloat;

  Result := nil;
  for i := 0 to FZjjlList.Count - 1 do
  begin
    vZ := TZjjl(FZjjlList.Items[i]);
    if SameText(vZ.FBillsCode, sCode) and SameText(vZ.FBillsName, sName) and SameText(vZ.FBillsUnits, sUnits) and
       (PriceRoundTo(fPrice - vZ.FBillsPrice) < 0.00001) and
       SameText(sDrawingCode, vZ.FFilterDrawingCode) then
    begin
      Result := vZ;
      Break;
    end;
  end;
end;

procedure TrmWeiWuZjjlGatherData.GatherZjjl(AProjectData: TProjectData);
var
  i: Integer;
  vNode: TBillsIDTreeNode;
  Rec, BillsRec, StageRec: TsdDataRecord;
  vZ: TZjjl;
begin
  for i := 0 to AProjectData.PhaseData.ZJJLData.sddZJJL.RecordCount - 1 do
  begin
    Rec := AProjectData.PhaseData.ZJJLData.sddZJJL.Records[I];
    vNode := TBillsIDTreeNode(AProjectData.BillsMeasureData.BillsMeasureTree.FindNode(Rec.ValueByName('BillsID').AsInteger));
    StageRec := AProjectData.PhaseData.StageData.StageRecord(Rec.ValueByName('BillsID').AsInteger);
    if Assigned(Rec) and Assigned(vNode) then
    begin
      vZ := FindZjjl(Rec, vNode);
      if not Assigned(vZ) then
      begin
        vZ := TZjjl.Create(Rec, StageRec, vNode);
        FZjjlList.Add(vZ);
      end
      else
        vZ.Merge(Rec, StageRec, vNode);
    end;
  end;
end;

procedure TrmWeiWuZjjlGatherData.WriteData;

  function GetCodeFormat(ACount: Integer): string;
  begin
    if ACount < 10 then
      Result := '-%d'
    else if ACount < 100 then
      REsult := '-%.2d'
    else if ACount < 1000 then
      Result := '-%.3d'
    else if ACount < 10000 then
      Result := '-%.4d'
    else if ACount < 100000 then
      Result := '-%.5d';
  end;

var
  i: Integer;
  vZ: TZjjl;
  sFormat: String;
begin
  cdsZjjl.Active := True;
  cdsZjjl.EmptyDataSet;
  if FPreText <> '' then
    sFormat := FPreText + Format('-%.2d', [FPhaseIndex]) + GetCodeFormat(FZjjlList.Count)
  else
    sFormat := FPreText + Format('%.2d', [FPhaseIndex]) + GetCodeFormat(FZjjlList.Count);
  for i := 0 to FZjjlList.Count - 1 do
  begin
    vZ := TZjjl(FZjjlList.Items[i]);

    cdsZjjl.Append;
    cdsZjjlCode.AsString := Format(sFormat, [i+1]);
    cdsZjjlCertificateCode.AsString := vZ.FCertificateCode;
    cdsZjjlBGLCode.AsString := vZ.FBGLCode;
    cdsZjjlPegName.AsString := vZ.FPegName;
    cdsZjjlBeginPeg.AsString := vZ.FBeginPeg;
    cdsZjjlEndPeg.AsString := vZ.FEndPeg;
    cdsZjjlFBFXName.AsString := vZ.FFBFXName;
    cdsZjjlUnitName.AsString := vZ.FUnitName;
    cdsZjjlDrawingCode.AsString := vZ.FDrawingCode;
    cdsZjjlFormulaMemo.AsString := vZ.FFormulaMemo;
    cdsZjjlRelaFile.AsString := vZ.FRelaFile;

    cdsZjjlBillsCode.AsString := vZ.FBillsCode;
    cdsZjjlBillsName.AsString := vZ.FBillsName;
    cdsZjjlBillsUnits.AsString := vZ.FBillsUnits;
    cdsZjjlBillsPrice.AsFloat := vZ.FBillsPrice;
    cdsZjjlFilterDrawingCode.AsString := vZ.FFilterDrawingCode;

    cdsZjjlBillsCurDealQuantity.AsFloat := vZ.FBillsCurDealQuantity;
    cdsZjjlBillsCurDealTotalPrice.AsFloat := vZ.FBillsCurDealTotalPrice;
    cdsZjjlBillsCurQcQuantity.AsFloat := vZ.FBillsCurQcQuantity;
    cdsZjjlBillsCurQcTotalPrice.AsFloat := vZ.FBillsCurQcTotalPrice;
    cdsZjjlBillsCurGatherQuantity.AsFloat := vZ.FBillsCurGatherQuantity;
    cdsZjjlBillsCurGatherTotalPrice.AsFloat := vZ.FBillsCurGatherTotalPrice;

    cdsZjjlBillsEndDealQuantity.AsFloat := vZ.FBillsEndDealQuantity;
    cdsZjjlBillsEndDealTotalPrice.AsFloat := vZ.FBillsEndDealTotalPrice;
    cdsZjjlBillsEndQcQuantity.AsFloat := vZ.FBillsEndQcQuantity;
    cdsZjjlBillsEndQcTotalPrice.AsFloat := vZ.FBillsEndQcTotalPrice;
    cdsZjjlBillsEndGatherQuantity.AsFloat := vZ.FBillsEndGatherQuantity;
    cdsZjjlBillsEndGatherTotalPrice.AsFloat := vZ.FBillsEndGatherTotalPrice;

    cdsZjjlBillsOrgQuantity.AsFloat := vZ.FBillsOrgQuantity;
    cdsZjjlBillsOrgTotalPrice.AsFloat := vZ.FBillsOrgTotalPrice;
    cdsZjjlBillsMisQuantity.AsFloat := vZ.FBillsMisQuantity;
    cdsZjjlBillsMisTotalPrice.AsFloat := vZ.FBillsMisTotalPrice;
    cdsZjjlBillsOthQuantity.AsFloat := vZ.FBillsOthQuantity;
    cdsZjjlBillsOthTotalPrice.AsFloat := vZ.FBillsOthTotalPrice;
    cdsZjjlBillsQuantity.AsFloat := vZ.FBillsQuantity;
    cdsZjjlBillsTotalPrice.AsFloat := vZ.FBillsTotalPrice;

    cdsZjjlFenBuName.AsString := vZ.FFenBuName;
    cdsZjjlDanWeiName.AsString := vZ.FDanWeiName;

    cdsZjjlProjectName.AsString := AProjectData.ProjProperties.ProjectName;
    cdsZjjlDealCode.AsString := AProjectData.ProjProperties.DealIndex;
    cdsZjjlCName.AsString := AProjectData.ProjProperties.CName;
    cdsZjjlSName.AsString := AProjectData.ProjProperties.SName;
    cdsZjjlPhaseIndex.AsString := Format('%d 期', [AProjectData.PhaseIndex]);
    cdsZjjlDealName.AsString := AProjectData.ProjProperties.DealName;
    cdsZjjlFlowIndex.AsInteger := 0;

    cdsZjjl.Post;
  end;
end;

end.
