tpGatherTree.pas 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. unit tpGatherTree;
  2. // 实际上可以使用mCacheTree中的ReportCacheTree
  3. // 但此处的树节点更多,使用的清单数据不多,为了便于理解,故重写
  4. interface
  5. uses
  6. Classes, CacheTree, mDataRecord, ZhAPI, sdDB, sdIDTree;
  7. type
  8. TtpGatherTreeNode = class(TCacheNode)
  9. private
  10. FCode: string;
  11. FB_Code: string;
  12. FName: string;
  13. FUnits: string;
  14. FPrice: Double;
  15. FQuantity: Double;
  16. FTotalPrice: Double;
  17. FDgnQuantity1: Double;
  18. FDgnQuantity2: Double;
  19. FRelaPeg: Boolean;
  20. FParted: Boolean;
  21. FDrawingCode: string;
  22. public
  23. property Code: string read FCode write FCode;
  24. property B_Code: string read FB_Code write FB_Code;
  25. property Name: string read FName write FName;
  26. property Units: string read FUnits write FUnits;
  27. property Price: Double read FPrice write FPrice;
  28. property Quantity: Double read FQuantity write FQuantity;
  29. property TotalPrice: Double read FTotalPrice write FTotalPrice;
  30. property DgnQuantity1: Double read FDgnQuantity1 write FDgnQuantity1;
  31. property DgnQuantity2: Double read FDgnQuantity2 write FDgnQuantity2;
  32. // 节点为桩号/节点的父项为桩号/节点的子项全为桩号
  33. property RelaPeg: Boolean read FRelaPeg write FRelaPeg;
  34. property Parted: Boolean read FParted write FParted;
  35. property DrawingCode: string read FDrawingCode write FDrawingCode;
  36. end;
  37. TtpGatherTree = class(TCacheTree)
  38. private
  39. function SamePrice(APrice1, APrice2: Double): Boolean;
  40. function GetParentParted(ANode: TtpGatherTreeNode): Boolean;
  41. procedure CheckNodeParted(ANode: TtpGatherTreeNode);
  42. function GetParentRelaPeg(ANode: TtpGatherTreeNode): Boolean;
  43. procedure CheckNodeRelaPeg(ANode: TtpGatherTreeNode);
  44. protected
  45. function GetNewNode: TCacheNode; override;
  46. public
  47. function FindNode(AParent: TtpGatherTreeNode; ARec: TBillsRecord): TtpGatherTreeNode;
  48. function FindNextSibling(AParent: TtpGatherTreeNode; ARec: TBillsRecord): TtpGatherTreeNode;
  49. function AddNode(AParent: TCacheNode; ANextSibling: TCacheNode = nil): TtpGatherTreeNode;
  50. procedure CalculateAllParent;
  51. procedure WriteData(ADataSet: TsdDataSet);
  52. procedure CheckRelaPeg;
  53. procedure CheckParted;
  54. end;
  55. implementation
  56. uses SysUtils;
  57. { TtpGatherTree }
  58. function TtpGatherTree.AddNode(AParent,
  59. ANextSibling: TCacheNode): TtpGatherTreeNode;
  60. begin
  61. Result := TtpGatherTreeNode(GetNewNode);
  62. if Assigned(ANextSibling) then
  63. ANextSibling.InsertPreSibling(Result)
  64. else if Assigned(AParent) then
  65. AParent.InsertChild(Result)
  66. else
  67. Root.InsertChild(Result);
  68. end;
  69. procedure TtpGatherTree.CalculateAllParent;
  70. function GatherChildren(ANode: TtpGatherTreeNode): Double;
  71. var
  72. vChild: TtpGatherTreeNode;
  73. begin
  74. Result := 0;
  75. if not Assigned(ANode) then Exit;
  76. vChild := TtpGatherTreeNode(ANode.FirstChild);
  77. while Assigned(vChild) do
  78. begin
  79. Result := Result + vChild.TotalPrice;
  80. vChild := TtpGatherTreeNode(vChild.NextSibling);
  81. end;
  82. end;
  83. procedure CalculateParent(ANode: TtpGatherTreeNode);
  84. begin
  85. if not Assigned(ANode) or not Assigned(ANode.FirstChild) then Exit;
  86. CalculateParent(TtpGatherTreeNode(ANode.FirstChild));
  87. ANode.TotalPrice := GatherChildren(ANode);
  88. CalculateParent(TtpGatherTreeNode(ANode.NextSibling));
  89. end;
  90. begin
  91. CalculateParent(TtpGatherTreeNode(Root.FirstChild));
  92. end;
  93. procedure TtpGatherTree.CheckNodeParted(ANode: TtpGatherTreeNode);
  94. begin
  95. if not Assigned(ANode) then Exit;
  96. if Assigned(ANode.FirstChild) then
  97. begin
  98. CheckNodeParted(TtpGatherTreeNode(ANode.FirstChild));
  99. ANode.Parted := GetParentParted(ANode);
  100. end;
  101. CheckNodeParted(TtpGatherTreeNode(ANode.NextSibling));
  102. end;
  103. procedure TtpGatherTree.CheckNodeRelaPeg(ANode: TtpGatherTreeNode);
  104. begin
  105. if not Assigned(ANode) then Exit;
  106. if Assigned(ANode.FirstChild) then
  107. begin
  108. CheckNodeRelaPeg(TtpGatherTreeNode(ANode.FirstChild));
  109. ANode.RelaPeg := GetParentRelaPeg(ANode);
  110. end;
  111. CheckNodeRelaPeg(TtpGatherTreeNode(ANode.NextSibling));
  112. end;
  113. procedure TtpGatherTree.CheckParted;
  114. begin
  115. CheckNodeParted(TtpGatherTreeNode(Root.FirstChild));
  116. end;
  117. procedure TtpGatherTree.CheckRelaPeg;
  118. begin
  119. CheckNodeRelaPeg(TtpGatherTreeNode(Root.FirstChild));
  120. end;
  121. function TtpGatherTree.FindNextSibling(AParent: TtpGatherTreeNode;
  122. ARec: TBillsRecord): TtpGatherTreeNode;
  123. var
  124. vNode: TtpGatherTreeNode;
  125. sCodeID, sCodeID2, sB_CodeID, sB_CodeID2: string;
  126. begin
  127. if Assigned(AParent) then
  128. vNode := TtpGatherTreeNode(AParent.FirstChild)
  129. else
  130. vNode := TtpGatherTreeNode(Root.FirstChild);
  131. Result := nil;
  132. if (ARec.Code.AsString = '') and (ARec.B_Code.AsString = '') then Exit;
  133. sCodeID := ConvertDigitCode(ARec.Code.AsString, 3, '-');
  134. sB_CodeID := ConvertDigitCode(ARec.B_Code.AsString, 4, '-');
  135. while Assigned(vNode) do
  136. begin
  137. sCodeID2 := ConvertDigitCode(vNode.Code, 3, '-');
  138. sB_CodeID2 := ConvertDigitCode(vNode.B_Code, 4, '-');
  139. if sCodeID < sCodeID2 then
  140. begin
  141. Result := vNode;
  142. Break;
  143. end
  144. else if sB_CodeID < sB_CodeID2 then
  145. begin
  146. Result := vNode;
  147. Break;
  148. end;
  149. vNode := TtpGatherTreeNode(vNode.NextSibling);
  150. end;
  151. end;
  152. function TtpGatherTree.FindNode(AParent: TtpGatherTreeNode; ARec: TBillsRecord): TtpGatherTreeNode;
  153. var
  154. vNode: TtpGatherTreeNode;
  155. begin
  156. if Assigned(AParent) then
  157. vNode := TtpGatherTreeNode(AParent.FirstChild)
  158. else
  159. vNode := TtpGatherTreeNode(Root.FirstChild);
  160. while Assigned(vNode) do
  161. begin
  162. if SameText(vNode.Code, ARec.Code.AsString) and
  163. SameText(vNode.B_Code, ARec.B_Code.AsString) and
  164. SameText(vNode.Name, ARec.Name.AsString) and
  165. SameText(vNode.Units, ARec.Units.AsString) and
  166. SamePrice(vNode.Price, ARec.Price.AsFloat) then
  167. begin
  168. Result := vNode;
  169. Break;
  170. end;
  171. vNode := TtpGatherTreeNode(vNode.NextSibling);
  172. end;
  173. end;
  174. function TtpGatherTree.GetNewNode: TCacheNode;
  175. begin
  176. Result := TtpGatherTreeNode.Create(Self, GetNewNodeID);
  177. CacheNodes.Add(Result);
  178. end;
  179. function TtpGatherTree.GetParentParted(ANode: TtpGatherTreeNode): Boolean;
  180. var
  181. i: Integer;
  182. vChild: TtpGatherTreeNode;
  183. begin
  184. if Assigned(ANode.FirstChild) then
  185. begin
  186. Result := True;
  187. vChild := TtpGatherTreeNode(ANode.FirstChild);
  188. while Assigned(vChild) and Result do
  189. begin
  190. Result := Result and vChild.Parted;
  191. vChild := TtpGatherTreeNode(vChild.NextSibling);
  192. end;
  193. end
  194. else
  195. Result := ANode.Parted;
  196. end;
  197. function TtpGatherTree.GetParentRelaPeg(ANode: TtpGatherTreeNode): Boolean;
  198. var
  199. i: Integer;
  200. vChild: TtpGatherTreeNode;
  201. begin
  202. if Assigned(ANode.FirstChild) then
  203. begin
  204. Result := True;
  205. vChild := TtpGatherTreeNode(ANode.FirstChild);
  206. while Assigned(vChild) and Result do
  207. begin
  208. Result := Result and vChild.RelaPeg;
  209. vChild := TtpGatherTreeNode(vChild.NextSibling);
  210. end;
  211. end
  212. else
  213. Result := ANode.RelaPeg;
  214. end;
  215. function TtpGatherTree.SamePrice(APrice1, APrice2: Double): Boolean;
  216. begin
  217. Result := (APrice1 - APrice2) < 0.001;
  218. end;
  219. procedure TtpGatherTree.WriteData(ADataSet: TsdDataSet);
  220. procedure BeforeWrite;
  221. begin
  222. ADataSet.DisableControls;
  223. ADataSet.BeginUpdate;
  224. ADataSet.DeleteAll;
  225. end;
  226. procedure AfterWrite;
  227. begin
  228. ADataSet.EndUpdate;
  229. ADataSet.EnableControls;
  230. end;
  231. var
  232. i: Integer;
  233. vNode: TtpGatherTreeNode;
  234. Rec: TsdDataRecord;
  235. begin
  236. BeforeWrite;
  237. try
  238. for i := 0 to CacheNodes.Count - 1 do
  239. begin
  240. vNode := TtpGatherTreeNode(CacheNodes.Items[i]);
  241. Rec := ADataSet.Add;
  242. Rec.ValueByName('ID').AsInteger := vNode.ID;
  243. Rec.ValueByName('ParentID').AsInteger := vNode.ParentID;
  244. Rec.ValueByName('NextSiblingID').AsInteger := vNode.NextSiblingID;
  245. Rec.ValueByName('Code').AsString := vNode.Code;
  246. Rec.ValueByName('B_Code').AsString := vNode.B_Code;
  247. Rec.ValueByName('Name').AsString := vNode.Name;
  248. Rec.ValueByName('Units').AsString := vNode.Units;
  249. Rec.ValueByName('Price').AsFloat := vNode.Price;
  250. Rec.ValueByName('Quantity').AsFloat := vNode.Quantity;
  251. Rec.ValueByName('TotalPrice').AsFloat := vNode.TotalPrice;
  252. Rec.ValueByName('DgnQuantity1').AsFloat := vNode.DgnQuantity1;
  253. Rec.ValueByName('DgnQuantity2').AsFloat := vNode.DgnQuantity2;
  254. Rec.ValueByName('DrawingCode').AsString := vNode.DrawingCode;
  255. end;
  256. finally
  257. AfterWrite;
  258. end;
  259. end;
  260. end.