unit ZJJLDm;

interface

uses
  ZjGrid,
  SysUtils, Classes, DB, DBClient, ADODB, sdIDTree, sdDB, Provider,
  Windows;

type
  TZJJLNode = class
  private
    FBillsID: Integer;
    FCode: string;
    FCertificateCode: string;
    FBillsCode: string;
    FFormulaMemo: string;
    FRelaFile: string;
    FType: Integer;
  end;

  TZJJLInfoRec = Record
    FBFXName: string;
    PegName: string;
    BGLCode: string;
    DrawingCode: string;
    UnitName: string;
  end;

  TZJJLData = class(TDataModule)
    atZJJL: TADOTable;
    dspZJJL: TDataSetProvider;
    cdsZJJL: TClientDataSet;
    cdsZJJLID: TIntegerField;
    cdsZJJLBillsID: TIntegerField;
    cdsZJJLCode: TWideStringField;
    cdsZJJLCertificateCode: TWideStringField;
    cdsZJJLBillsCode: TWideStringField;
    cdsZJJLFormulaMemo: TMemoField;
    cdsZJJLRelaFile: TWideStringField;
    cdsZJJLType: TIntegerField;

    cdsZJJLView: TClientDataSet;
    cdsZJJLViewID: TIntegerField;
    cdsZJJLViewBillsID: TIntegerField;
    cdsZJJLViewCode: TWideStringField;
    cdsZJJLViewCertificateCode: TWideStringField;
    cdsZJJLViewBillsCode: TWideStringField;
    cdsZJJLViewFormulaMemo: TMemoField;
    cdsZJJLViewRelaFile: TWideStringField;
    cdsZJJLViewType: TIntegerField;
    procedure cdsZJJLViewAfterScroll(DataSet: TDataSet);
  private
    FPhaseData: TObject;
    FCanModified: Boolean;
    FNewID: Integer;
    FOrgDataList: TList;
    FDetailGrid: TZJGrid;

    procedure GenerateZJJLNode(ANode: TsdIDTreeNode; AType: Integer);

    function CheckLastXmj(AID: Integer): Boolean;
    function CheckBGExist(ANode: TsdIDTreeNode): Boolean;
    function CheckMeasureExist(ANode: TsdIDTreeNode): Boolean;
    procedure GenerateLastXmj(ANode: TsdIDTreeNode);
    procedure GenerateNode(ANode: TsdIDTreeNode);

    procedure GenerateLeafNode(ANode: TsdIDTreeNode);
    procedure GenerateNodeByB_Code(ANode: TsdIDTreeNode);

    procedure DeleteAll;
    procedure RestoreOrgData;

    procedure DetailGridCellCanEdit(Sender: TObject; const ACoord: TPoint;
      var Allow: Boolean);
    procedure DetailGridCellTextChanged(Sender: TObject; Col, Row: Integer);

    function GetMainBillsTree: TsdIDTree;
  public
    constructor Create(APhaseData: TObject);
    destructor Destroy; override;

    procedure Open(AConnection: TADOConnection);
    procedure Save;

    procedure GenerateAll;
    procedure GenerateAllByB_Code;
    procedure AssignedCurData;

    function GetInfoRecByCode(ABillsID: Integer): TZJJLInfoRec;
    function GetInfoRecByB_Code(ABillsID: Integer): TZJJLInfoRec;
    function GetInfoRec(ABillsID, AType: Integer): TZJJLInfoRec;

    procedure LocateBills;

    property PhaseData: TObject read FPhaseData;
    property MainBillsTree: TsdIDTree read GetMainBillsTree;
    property CanModified: Boolean read FCanModified write FCanModified;
    property DetailGrid: TZJGrid read FDetailGrid;
  end;

implementation

uses
  PhaseData, ProjectData, BillsDm, UtilMethods, ProjectProperty, ZhAPI,
  BillsCompileDm, BillsMeasureDm;

{$R *.dfm}

{ TZJJLData }

constructor TZJJLData.Create(APhaseData: TObject);
begin
  inherited Create(nil);
  FPhaseData := APhaseData;
  FOrgDataList := TList.Create;
  FDetailGrid := TZJGrid.Create(nil);
  FDetailGrid.Options := FDetailGrid.Options + [goWarpText];
  FDetailGrid.OnCellCanEdit := DetailGridCellCanEdit;
  FDetailGrid.OnCellTextChanged := DetailGridCellTextChanged;
end;

destructor TZJJLData.Destroy;
begin
  FDetailGrid.Free;
  ClearObjects(FOrgDataList);
  FOrgDataList.Free;
  inherited;
end;

function TZJJLData.GetMainBillsTree: TsdIDTree;
begin
  with TProjectData(TPhaseData(FPhaseData).ProjectData) do
    Result := BillsMeasureData.BillsMeasureTree;
end;

procedure TZJJLData.Open(AConnection: TADOConnection);
begin
  atZJJL.Connection := AConnection;
  cdsZJJL.Open;
  cdsZJJL.IndexFieldNames := 'ID';
  cdsZJJLView.CloneCursor(cdsZJJL, True);
  cdsZJJLView.IndexFieldNames := 'ID';
end;

procedure TZJJLData.Save;
begin
  cdsZJJL.ApplyUpdates(0);
end;

function TZJJLData.CheckLastXmj(AID: Integer): Boolean;
var
  stnNode, stnChild: TsdIDTreeNode;
begin
  stnNode := MainBillsTree.FindNode(AID);
  Result := stnNode.Rec.ValueByName('Code').AsString <> '';
  if not stnNode.HasChildren or not Result then Exit;
  stnChild := stnNode.FirstChild;
  Result := stnChild.Rec.ValueByName('B_Code').AsString <> '';
end;

procedure TZJJLData.AssignedCurData;
var
  iRowIndex: Integer;
  InfoRec: TZJJLInfoRec;
begin
  FDetailGrid.OnCellTextChanged := nil;
  FDetailGrid.FixedRowCount := 0;
  FDetailGrid.FixedColCount := 0;
  FDetailGrid.ColCount := 1;
  FDetailGrid.RowCount := 9;
  FDetailGrid.DefaultColWidth := 300;
  for iRowIndex := 0 to FDetailGrid.RowCount - 1 do
    FDetailGrid[0, iRowIndex].Align := gaTopLeft;
  InfoRec := GetInfoRec(cdsZJJLViewBillsID.AsInteger, cdsZJJLViewType.AsInteger);
  FDetailGrid.Cells[0, 0].Text := '变更令号：' + InfoRec.BGLCode;
  FDetailGrid.Cells[0, 1].Text := '桩号或部位：' + InfoRec.PegName;
  FDetailGrid.Cells[0, 2].Text := '分部分项工程：' + InfoRec.FBFXName;
  FDetailGrid.Cells[0, 3].Text := '计量单元：' + InfoRec.UnitName;
  FDetailGrid.Cells[0, 4].Text := '图号：' + InfoRec.DrawingCode;
  FDetailGrid.Cells[0, 5].Text := '计算式说明：';
  FDetailGrid.Cells[0, 6].Text := cdsZJJLViewFormulaMemo.AsString;
  FDetailGrid.Cells[0, 6].Align := gaTopLeft;
  FDetailGrid.RowHeights[6] := 57;
  FDetailGrid.Cells[0, 7].Text := '计算草图几何尺寸：';
  FDetailGrid.Cells[0, 8].Text := cdsZJJLViewRelaFile.AsString;
  FDetailGrid.Cells[0, 8].Align := gaTopLeft;
  FDetailGrid.RowHeights[8] := 57;
  FDetailGrid.OnCellTextChanged := DetailGridCellTextChanged;
end;

procedure TZJJLData.GenerateAll;
begin
  RestoreOrgData;
  FNewID := 1;
  DeleteAll;
  GenerateNode(MainBillsTree.FirstNode);
end;

procedure TZJJLData.GenerateNode(ANode: TsdIDTreeNode);
begin
  if not Assigned(ANode) then Exit;
  if CheckLastXmj(ANode.ID) then
    GenerateLastXmj(ANode)
  else
    GenerateNode(ANode.FirstChild);
  GenerateNode(ANode.NextSibling);
end;

procedure TZJJLData.GenerateLastXmj(ANode: TsdIDTreeNode);
begin
  if CheckMeasureExist(ANode) then
    GenerateZJJLNode(ANode, 0);
end;

function TZJJLData.CheckBGExist(ANode: TsdIDTreeNode): Boolean;

  function CheckBGLExist(AID: Integer): Boolean;
  var
    StageRec: TsdDataRecord;
  begin
    StageRec := TPhaseData(FPhaseData).StageData.StageRecord(AID);
    Result := Assigned(StageRec) and
           ((StageRec.ValueByName('QcBGLCode').AsString <> '')
           or (StageRec.ValueByName('PcBGLCode').AsString <> ''));
  end;

var
  iChild: Integer;
begin
  Result := False;
  if not Assigned(ANode) then Exit;
  if ANode.HasChildren then
  begin
    for iChild := 0 to ANode.ChildCount - 1 do
    begin
      Result := Result or CheckBGExist(ANode.ChildNodes[iChild]);
      if Result then Break;
    end;
  end
  else
    Result := CheckBGLExist(ANode.ID);
end;

procedure TZJJLData.DeleteAll;
begin
  cdsZJJL.First;
  while not cdsZJJL.Eof do
    cdsZJJL.Delete;
end;

procedure TZJJLData.RestoreOrgData;

  function CreateNodeData: TZJJLNode;
  begin
    Result := TZJJLNode.Create;
    Result.FBillsID := cdsZJJLBillsID.AsInteger;
    Result.FCode := cdsZJJLCode.AsString;
    Result.FCertificateCode := cdsZJJLCertificateCode.AsString;
    Result.FBillsCode := cdsZJJLBillsCode.AsString;
    Result.FFormulaMemo := cdsZJJLFormulaMemo.AsString;
    Result.FRelaFile := cdsZJJLRelaFile.AsString;
    Result.FType := cdsZJJLType.AsInteger;
  end;

begin
  FOrgDataList.Clear;
  cdsZJJL.First;
  while not cdsZJJL.Eof do
  begin
    FOrgDataList.Add(CreateNodeData);
    cdsZJJL.Next;
  end;
end;

function TZJJLData.CheckMeasureExist(ANode: TsdIDTreeNode): Boolean;

  function CheckStageCompleteData(AID: Integer): Boolean;
  var
    StageRec: TsdDataRecord;
  begin
    StageRec := TPhaseData(FPhaseData).StageData.StageRecord(AID);
    Result := Assigned(StageRec) and
           ((StageRec.ValueByName('GatherQuantity').AsFloat <> 0)
           or (StageRec.ValueByName('GatherTotalPrice').AsFloat <> 0));
  end;

var
  iChild: Integer;
begin
  Result := False;
  if not Assigned(ANode) then Exit;
  if ANode.HasChildren then
  begin
    for iChild := 0 to ANode.ChildCount - 1 do
    begin
      Result := Result or CheckMeasureExist(ANode.ChildNodes[iChild]);
      if Result then Break;
    end;
  end
  else
    Result := CheckStageCompleteData(ANode.ID);
end;

procedure TZJJLData.cdsZJJLViewAfterScroll(DataSet: TDataSet);
begin
  AssignedCurData;
end;

procedure TZJJLData.DetailGridCellCanEdit(Sender: TObject;
  const ACoord: TPoint; var Allow: Boolean);
begin
  Allow := ((ACoord.Y = 6) or (ACoord.Y = 8)) and
      not TPhaseData(FPhaseData).StageDataReadOnly;
end;

function TZJJLData.GetInfoRecByCode(ABillsID: Integer): TZJJLInfoRec;

  function GetBGLCode(ANode: TsdIDTreeNode): string;
  begin
    with TProjectData(TPhaseData(FPhaseData).ProjectData) do
      Result := BillsMeasureData.GatherRelaBGL(ANode);
  end;

  function GetPegName(APegNode: TsdIDTreeNode): string;
  begin
    if Assigned(APegNode) then
      Result := APegNode.Rec.ValueByName('Name').AsString
    else
      Result := '';
  end;

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

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

  function GetFBFXName(ANode, APegNode: TsdIDTreeNode): string;
  var
    vCurNode: TsdIDTreeNode;
  begin
    Result := '';
    if not Assigned(ANode) then Exit;
    // 如果计量单元节点的名称为桩号（转化为判断计量单元节点与桩号节点为同一个）
    if not Assigned(APegNode) or (ANode.ID = APegNode.ID) then
    begin
      // 取树结构的第三、四层节点的名称
      Result := GetNameByLevel(ANode, 2);
      if (Result <> '') and (GetNameByLevel(ANode, 3) <> '') then
        Result := Result + ',';
      Result := Result + GetNameByLevel(ANode, 3);
    end
    // 否则，合并[桩号节点的子节点]至[计量单元节点的父节点]的名称
    else
    begin
      vCurNode := ANode.Parent;
      // 转化为判断层次，层次大于[桩号节点的子节点]的层次
      while vCurNode.Level > APegNode.Level do
      begin
        Result := vCurNode.Rec.ValueByName('Name').AsString + ',' + Result;
        vCurNode := vCurNode.Parent;
      end;
    end;
  end;

  function GetFieldStrDef(ANode: TsdIDTreeNode; const AFieldName, ADef: string): string;
  begin
    if Assigned(ANode) then
      Result := ANode.Rec.ValueByName(AFieldName).AsString
    else
      Result := '';
  end;

var
  vPeg, vNode: TsdIDTreeNode;
begin
  vNode := MainBillsTree.FindNode(ABillsID);
  vPeg := GetPegNode(vNode);
  Result.BGLCode := GetBGLCode(vNode);
  Result.PegName := GetPegName(vPeg);
  Result.FBFXName := GetFBFXName(vNode, vPeg);
  Result.UnitName := GetFieldStrDef(vNode, 'Name', '');
  Result.DrawingCode := GetFieldStrDef(vNode, 'DrawingCode', '');
end;

procedure TZJJLData.DetailGridCellTextChanged(Sender: TObject; Col,
  Row: Integer);
begin
  if (Row = 6) then
  begin
    cdsZJJLView.Edit;
    cdsZJJLViewFormulaMemo.AsString := TZJGrid(Sender).Cells[Col, Row].Text;
    cdsZJJLView.Post;
  end
  else if (Row = 8) then
  begin
    cdsZJJLView.Edit;
    cdsZJJLViewRelaFile.AsString := TZJGrid(Sender).Cells[Col, Row].Text;
    cdsZJJLView.Post;
  end;
end;

procedure TZJJLData.GenerateAllByB_Code;
begin
  RestoreOrgData;
  FNewID := 1;
  DeleteAll;
  GenerateNodeByB_Code(MainBillsTree.FirstNode);
end;

procedure TZJJLData.GenerateNodeByB_Code(ANode: TsdIDTreeNode);
begin
  if not Assigned(ANode) then Exit;
  if ANode.HasChildren then
    GenerateNodeByB_Code(ANode.FirstChild)
  else
    GenerateLeafNode(ANode);
  GenerateNodeByB_Code(ANode.NextSibling);
end;

procedure TZJJLData.GenerateLeafNode(ANode: TsdIDTreeNode);

  function CheckMeasureExist(AID: Integer): Boolean;
  var
    StageRec: TsdDataRecord;
  begin
    StageRec := TPhaseData(FPhaseData).StageData.StageRecord(AID);
    Result := Assigned(StageRec) and
           ((StageRec.ValueByName('GatherQuantity').AsFloat <> 0)
           or (StageRec.ValueByName('GatherTotalPrice').AsFloat <> 0));
  end;

begin
  if (ANode.Rec.ValueByName('B_Code').AsString <> '') and
      CheckMeasureExist(ANode.ID) then
    GenerateZJJLNode(ANode, 1);
end;

procedure TZJJLData.GenerateZJJLNode(ANode: TsdIDTreeNode;
  AType: Integer);

  function GetNewCode: string;
  begin
    with TProjectData(TPhaseData(FPhaseData).ProjectData) do
    begin
      Result := ProjProperties.ZJJLPreText;
      if (Result <> '') and (Result[Length(Result)] <> '-') then
        Result := Result + '-';
      Result := Result + Format('%d-%d', [PhaseIndex, FNewID]);
    end;
  end;

  function GetOrgZJJLNode(ABillsID: Integer): TZJJLNode;
  var
    iIndex: Integer;
  begin
    Result := nil;
    for iIndex := 0 to FOrgDataList.Count - 1 do
      // 7/30新增了一个“总量控制”模式，Type字段控制。真的是要疯掉了。
      if (TZJJLNode(FOrgDataList.Items[iIndex]).FBillsID = ABillsID)
          and (TZJJLNode(FOrgDataList.Items[iIndex]).FType = AType) then
      begin
        Result := TZJJLNode(FOrgDataList.Items[iIndex]);
        Break;
      end;
  end;

var
  ZJJLNode: TZJJLNode;
begin
  cdsZJJL.Append;
  cdsZJJLID.AsInteger := FNewID;
  cdsZJJLBillsID.AsInteger := ANode.ID;
  cdsZJJLType.AsInteger := AType;
  ZJJLNode := GetOrgZJJLNode(ANode.ID);
  if not Assigned(ZJJLNode) then
  begin
    cdsZJJLCode.AsString := GetNewCode;
    cdsZJJLBillsCode.AsString := ANode.Rec.ValueByName('Code').AsString;
  end
  else
  begin
    cdsZJJLCode.AsString := ZJJLNode.FCode;
    cdsZJJLCertificateCode.AsString := ZJJLNode.FCertificateCode;
    cdsZJJLBillsCode.AsString := ZJJLNode.FBillsCode;
    cdsZJJLFormulaMemo.AsString := ZJJLNode.FFormulaMemo;
    cdsZJJLRelaFile.AsString := ZJJLNode.FRelaFile;
  end;
  cdsZJJL.Post;
  Inc(FNewID);
end;

function TZJJLData.GetInfoRecByB_Code(ABillsID: Integer): TZJJLInfoRec;

  function GetBGLCode(ANode: TsdIDTreeNode): string;
  begin
    with TProjectData(TPhaseData(FPhaseData).ProjectData) do
      Result := BillsMeasureData.GatherRelaBGL(ANode);
  end;

var
  vNode: TsdIDTreeNode;
begin
  vNode := MainBillsTree.FindNode(ABillsID);
  Result.BGLCode := GetBGLCode(vNode);
  if Assigned(vNode.Parent) then
    Result.PegName := vNode.Parent.Rec.ValueByName('Name').AsString;
  Result.FBFXName := '';
  Result.UnitName := '';
  Result.DrawingCode := vNode.Rec.ValueByName('DrawingCode').AsString;
end;

function TZJJLData.GetInfoRec(ABillsID, AType: Integer): TZJJLInfoRec;
begin
  if AType = 0 then
    Result := GetInfoRecByCode(ABillsID)
  else if AType = 1 then
    Result := GetInfoRecByB_Code(ABillsID);
end;

procedure TZJJLData.LocateBills;
var
  Rec: TsdDataRecord;
begin
  with TProjectData(TPhaseData(FPhaseData).ProjectData) do
  begin
    Rec := BillsData.sddBills.FindKey('idxID', cdsZJJLViewBillsID.AsInteger);
    BillsMeasureData.sdvBillsMeasure.LocateInControl(Rec);
  end;
end;

end.
