unit BillsTree; interface uses sdIDTree, sdDB, mDataRecord; type TBillsIDTreeNode = class(TsdIDTreeNode) private FDealQuantity: Double; FDealTotalPrice: Double; FQcQuantity: Double; FQcTotalPrice: Double; FPcQuantity: Double; FPcTotalPrice: Double; FGatherTotalPrice: Double; FGatherQuantity: Double; FStageRec: TStageRecord; function HasCountPrice: Boolean; function HasTotalPrice: Boolean; function GetRec: TBillsRecord; public function CanUpLevel: Boolean; override; function CanDownLevel: Boolean; override; function CanUpMove: Boolean; override; function CanDownMove: Boolean; override; function UpLevel: Boolean; override; function DownLevel: Boolean; override; function HasMeasure: Boolean; function HasLedger: Boolean; function CountPriceEnable: Boolean; function TotalPriceEnable: Boolean; property Rec: TBillsRecord read GetRec; property DealQuantity: Double read FDealQuantity write FDealQuantity; property DealTotalPrice: Double read FDealTotalPrice write FDealTotalPrice; property QcQuantity: Double read FQcQuantity write FQcQuantity; property QcTotalPrice: Double read FQcTotalPrice write FQcTotalPrice; property PcQuantity: Double read FPcQuantity write FPcQuantity; property PcTotalPrice: Double read FPcTotalPrice write FPcTotalPrice; property GatherQuantity: Double read FGatherQuantity write FGatherQuantity; property GatherTotalPrice: Double read FGatherTotalPrice write FGatherTotalPrice; // Cache Data property StageRec: TStageRecord read FStageRec write FStageRec; end; TbitAfterDeleteNode = procedure (AParent: TsdIDTreeNode) of object; TBillsIDTree = class(TsdIDTree) private FDoOnAfterDeleteNode: TbitAfterDeleteNode; protected function CreateItem: TsdIDTreeNode; override; public function CanDelete(ANode: TsdIDTreeNode): Boolean; override; function DeleteNode(ANode: TsdIDTreeNode): Boolean; override; function Add(AParentID, ANextSiblingID: TsdTreeNodeID): TsdIDTreeNode; override; property DoOnAfterDeleteNode: TbitAfterDeleteNode read FDoOnAfterDeleteNode write FDoOnAfterDeleteNode; end; TEstimateIDTreeNode = class(TsdIDTreeNode) public function CanExpand: Boolean; override; end; TEstimateIDTree = class(TsdIDTree) public function CreateItem: TsdIDTreeNode; override; end; implementation { TBillsIDTree } function TBillsIDTree.Add(AParentID, ANextSiblingID: TsdTreeNodeID): TsdIDTreeNode; begin // 不允许插入首层节点 if (Selected <> nil) and (Selected.Level = 0) then Result := inherited Add(Selected.ID, -1) else Result := inherited Add(AParentID, ANextSiblingID); end; function TBillsIDTree.CanDelete(ANode: TsdIDTreeNode): Boolean; begin Result := Inherited CanDelete(ANode) and (ANode.ID >= 100) and (not ANode.Rec.ValueByName('LockedLevel').AsBoolean) and (ANode.Rec.ValueByName('AddDealQuantity').AsFloat = 0) and (ANode.Rec.ValueByName('AddDealTotalPrice').AsFloat = 0) and (ANode.Rec.ValueByName('AddQcQuantity').AsFloat = 0) and (ANode.Rec.ValueByName('AddQcTotalPrice').AsFloat = 0) and (ANode.Rec.ValueByName('AddPcQuantity').AsFloat = 0) and (ANode.Rec.ValueByName('AddPcTotalPrice').AsFloat = 0); end; function TBillsIDTree.CreateItem: TsdIDTreeNode; begin Result := TBillsIDTreeNode.Create(Self); end; function TBillsIDTree.DeleteNode(ANode: TsdIDTreeNode): Boolean; var vParent: TsdIDTreeNode; begin vParent := ANode.Parent; Result := inherited DeleteNode(ANode); if Assigned(FDoOnAfterDeleteNode) then FDoOnAfterDeleteNode(vParent); end; { TBillsIDTreeNode } function TBillsIDTreeNode.CanDownLevel: Boolean; begin Result := Inherited CanDownLevel and (Level > 0) and (not Rec.ValueByName('LockedLevel').AsBoolean) and not HasMeasure; if Assigned(PrevSibling) then begin Result := Result and (PrevSibling.HasChildren or not TBillsIDTreeNode(PrevSibling).HasMeasure); end; end; function TBillsIDTreeNode.CanDownMove: Boolean; begin Result := Inherited CanDownMove and (not Rec.ValueByName('LockedLevel').AsBoolean); end; function TBillsIDTreeNode.CanUpLevel: Boolean; var vNextSibling: TsdIDTreeNode; begin Result := Inherited CanUpLevel and (Level > 1) and (not Rec.ValueByName('LockedLevel').AsBoolean) and not HasMeasure; vNextSibling := NextSibling; while Assigned(vNextSibling) and Result do begin Result := Result and not TBillsIDTreeNode(NextSibling).HasMeasure; vNextSibling := vNextSibling.NextSibling; end; end; function TBillsIDTreeNode.CanUpMove: Boolean; begin Result := Inherited CanUpMove and (not Rec.ValueByName('LockedLevel').AsBoolean); end; function TBillsIDTreeNode.CountPriceEnable: Boolean; begin Result := HasCountPrice or (not HasTotalPrice); end; function TBillsIDTreeNode.DownLevel: Boolean; begin Result := inherited DownLevel; // 如升级后变为父项,则清空数量、单价 if Assigned(Parent) then begin Parent.Rec.ValueByName('Quantity').AsFloat := 0; Parent.Rec.ValueByName('Price').AsFloat := 0; end; end; function TBillsIDTreeNode.GetRec: TBillsRecord; begin Result := TBillsRecord(TsdIDTreeNode(Self).Rec); end; function TBillsIDTreeNode.HasCountPrice: Boolean; begin Result := False; if not Assigned(Rec) then Exit; Result := (Rec.Price.AsFloat <> 0) or (Rec.OrgQuantity.AsFloat <> 0) or (Rec.MisQuantity.AsFloat <> 0) or (Rec.OthQuantity.AsFloat <> 0) or (Rec.AddDealQuantity.AsFloat <> 0) or (Rec.AddQcQuantity.AsFloat <> 0) or (Rec.AddPcQuantity.AsFloat <> 0); end; function TBillsIDTreeNode.HasLedger: Boolean; begin Result := False; if not Assigned(Rec) then Exit; Result := (Rec.Price.AsFloat <> 0) or (Rec.Quantity.AsFloat <> 0); end; function TBillsIDTreeNode.HasMeasure: Boolean; begin Result := False; if not Assigned(Rec) then Exit; Result := (Rec.AddDealQuantity.AsFloat <> 0) or (Rec.AddDealTotalPrice.AsFloat <> 0) or (Rec.AddQcQuantity.AsFloat <> 0) or (Rec.AddQcTotalPrice.AsFloat <> 0) or (Rec.AddPcQuantity.AsFloat <> 0) or (Rec.AddPcTotalPrice.AsFloat <> 0); end; function TBillsIDTreeNode.HasTotalPrice: Boolean; begin Result := False; if not Assigned(Rec) then Exit; Result := (Rec.OrgTotalPrice.AsFloat <> 0) or (Rec.MisTotalPrice.AsFloat <> 0) or (Rec.OthTotalPrice.AsFloat <> 0) or (Rec.AddDealTotalPrice.AsFloat <> 0) or (Rec.AddQcTotalPrice.AsFloat <> 0) or (Rec.AddPcTotalPrice.AsFloat <> 0); end; function TBillsIDTreeNode.TotalPriceEnable: Boolean; begin Result := not HasCountPrice; end; function TBillsIDTreeNode.UpLevel: Boolean; begin Result := inherited UpLevel; // 如升级后变为父项,则清空数量、单价 if HasChildren then begin Rec.ValueByName('Quantity').AsFloat := 0; Rec.ValueByName('Price').AsFloat := 0; end; end; { TEstimateIDTreeNode } function TEstimateIDTreeNode.CanExpand: Boolean; var iChild: Integer; vChild: TsdIDTreeNode; begin Result := True; if HasChildren then for iChild := 0 to ChildCount - 1 do begin vChild := ChildNodes[iChild]; if vChild.Rec.ValueByName('B_Code').AsString <> '' then begin Result := False; Break; end; end; end; { TEstimateIDTree } function TEstimateIDTree.CreateItem: TsdIDTreeNode; begin Result := TEstimateIDTreeNode.Create(Self); end; end.