stgGather.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. unit stgGather;
  2. interface
  3. uses
  4. Classes, stgGatherCacheData, ProjectData, BillsTree, sdIDTree;
  5. type
  6. TstgSumBaseFileLoader = class
  7. private
  8. FTree: TstgGatherTree;
  9. FSumBaseFile: string;
  10. FTempFolder: string;
  11. FFileName: string;
  12. FProjectData: TProjectData;
  13. procedure LoadFileName;
  14. function LoadTreeNodeData(ANode: TBillsIDTreeNode; AParent: TstgGatherTreeNode): TstgGatherTreeNode;
  15. procedure LoadSumBaseTreeNode(ANode: TsdIDTreeNode; AParent: TstgGatherTreeNode);
  16. public
  17. constructor Create(ATree: TstgGatherTree; const ASumBaseFile: string);
  18. destructor Destroy; override;
  19. procedure LoadData;
  20. end;
  21. TstgSubTenderFileGather = class
  22. private
  23. FCacheData: TstgGatherCacheData;
  24. FProjectData: TProjectData;
  25. FCurSubTenderID: Integer;
  26. procedure GatherDetailData(AGatherNode: TstgGatherTreeNode; ASourceNode: TMeasureBillsIDTreeNode);
  27. function GatherSubTenderTreeNodeData(ANode: TsdIDTreeNode; AParent: TstgGatherTreeNode): TstgGatherTreeNode;
  28. procedure GatherSubTenderTreeNode(ANode: TsdIDTreeNode; AParent: TstgGatherTreeNode);
  29. procedure GatherSubTender(ASubTenderID: Integer);
  30. public
  31. procedure GatherTo(AGatherCacheData: TstgGatherCacheData; ASubTenders: TList);
  32. end;
  33. TstgErrorChecker = class
  34. private
  35. FCacheData: TstgGatherCacheData;
  36. procedure NewError(ANode: TstgGatherTreeNode; AType: Integer);
  37. function SafeCheckParent(ANode, ACheckParent: TstgGatherTreeNode): TstgGatherTreeNode;
  38. // ACheckParent的子项(总包中存在),存在与ANode同编号节点
  39. function HasSameCodeLevelChild(ANode: TstgGatherTreeNode;
  40. ACheckParent: tstgGatherTreeNode = nil): Boolean;
  41. // ACheckParent的子项(总包中存在),存在与ANode同编号、名称、单位,但不同层次节点
  42. function HasSameChildWithDiffLevel(ANode: TstgGatherTreeNode;
  43. ACheckParent: TstgGatherTreeNode = nil): Boolean;
  44. // ACheckParent的子项(总包中存在)(含子项的子项),存在与ANode同编号节点
  45. // 子项(含子项的子项),存在与CheckParent的子项(总包中存在)同编号节点
  46. function HasShortRelaCodeChild(ANode: TstgGatherTreeNode): Boolean;
  47. function HasLongRelaCodeChild(ANode:TstgGatherTreeNode): Boolean;
  48. function HasXmjChildWithSameCodeChild(ANode: TstgGatherTreeNode): Boolean;
  49. procedure AddXmjError(ANode: TstgGatherTreeNode);
  50. procedure AddGclError(ANode: TstgGatherTreeNode);
  51. procedure AddError(ANode: TstgGatherTreeNode);
  52. public
  53. procedure Check(AGatherCacheData: TstgGatherCacheData);
  54. end;
  55. implementation
  56. uses Math, Globals, mDataRecord, UtilMethods, SysUtils, XMLDoc, XMLIntf,
  57. CacheTree;
  58. { TstgSumBaseFileLoader }
  59. constructor TstgSumBaseFileLoader.Create(ATree: TstgGatherTree;
  60. const ASumBaseFile: string);
  61. begin
  62. FTree := ATree;
  63. FSumBaseFile := ASumBaseFile;
  64. FTempFolder := GenerateTempFolder(GetTempFilePath);
  65. FProjectData := TProjectData.Create;
  66. end;
  67. destructor TstgSumBaseFileLoader.Destroy;
  68. begin
  69. if FileExists(FTempFolder) then
  70. DeleteFolder(FTempFolder);
  71. if Assigned(FProjectData) then
  72. FProjectData.Free;
  73. inherited;
  74. end;
  75. procedure TstgSumBaseFileLoader.LoadData;
  76. begin
  77. UnZipFile(FSumBaseFile, FTempFolder);
  78. LoadFileName;
  79. FProjectData.OpenForSumUpBase(FTempFolder + '\' + FFileName);
  80. LoadSumBaseTreeNode(FProjectData.BillsCompileData.BillsCompileTree.FirstNode, nil);
  81. FTree.MarkLeafXmj;
  82. end;
  83. procedure TstgSumBaseFileLoader.LoadFileName;
  84. var
  85. FXmlDocument: IXMLDocument;
  86. RootXmlNode, InfoXmlNode: IXMLNode;
  87. ChildNodes: IXMLNodeList;
  88. begin
  89. FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument;
  90. try
  91. FXmlDocument.LoadFromFile(FTempFolder + '\Info.xml');
  92. FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAutoPrefix,doNamespaceDecl];
  93. RootXmlNode := FXmlDocument.DocumentElement;
  94. ChildNodes := RootXmlNode.ChildNodes;
  95. InfoXmlNode := ChildNodes.FindNode('ProjectInfo');
  96. FFileName := InfoXmlNode.Attributes['FileName'];
  97. finally
  98. FXmlDocument := nil;
  99. end;
  100. end;
  101. procedure TstgSumBaseFileLoader.LoadSumBaseTreeNode(ANode: TsdIDTreeNode; AParent: TstgGatherTreeNode);
  102. var
  103. vCurGatherNode: TstgGatherTreeNode;
  104. begin
  105. if not Assigned(ANode) then Exit;
  106. vCurGatherNode := LoadTreeNodeData(TBillsIDTreeNode(ANode), AParent);
  107. LoadSumBaseTreeNode(ANode.FirstChild, vCurGatherNode);
  108. LoadSumBaseTreeNode(ANode.NextSibling, AParent);
  109. end;
  110. function TstgSumBaseFileLoader.LoadTreeNodeData(ANode: TBillsIDTreeNode;
  111. AParent: TstgGatherTreeNode): TstgGatherTreeNode;
  112. begin
  113. Result := FTree.AddSumBaseNode(AParent, ANode.ID);
  114. Result.Code := ANode.Rec.Code.AsString;
  115. Result.B_Code := ANode.Rec.B_Code.AsString;
  116. Result.Name := ANode.Rec.Name.AsString;
  117. Result.Units := ANode.Rec.Units.AsString;
  118. end;
  119. { TstgSubTenderFileGather }
  120. procedure TstgSubTenderFileGather.GatherDetailData(
  121. AGatherNode: TstgGatherTreeNode; ASourceNode: TMeasureBillsIDTreeNode);
  122. var
  123. vSubTender: TstgSubTenderStageData;
  124. begin
  125. //if Assigned(ASourceNode.StageRec) and
  126. // ((ASourceNode.StageRec.GatherQuantity.AsFloat <> 0) or (ASourceNode.StageRec.GatherTotalPrice.AsFloat <> 0)) then
  127. if not ASourceNode.HasChildren then
  128. begin
  129. vSubTender := AGatherNode.SafeSubTender(FCurSubTenderID);
  130. vSubTender.AddDetail(ASourceNode);
  131. end;
  132. end;
  133. procedure TstgSubTenderFileGather.GatherSubTender(ASubTenderID: Integer);
  134. var
  135. vNode: TsdIDTreeNode;
  136. begin
  137. FCurSubTenderID := ASubTenderID;
  138. vNode := ProjectManager.ProjectsTree.FindNode(ASubTenderID);
  139. if vNode.Rec.ValueByName('Type').AsInteger = 1 then
  140. begin
  141. FProjectData := TProjectData.Create;
  142. try
  143. FProjectData.OpenForSumUpGather(GetMyProjectsFilePath + vNode.Rec.ValueByName('FileName').AsString);
  144. FCacheData.AddSubTender(vNode.Rec);
  145. GatherSubTenderTreeNode(FProjectData.BillsMeasureData.BillsMeasureTree.FirstNode, nil);
  146. finally
  147. FProjectData.Free;
  148. end;
  149. end;
  150. end;
  151. procedure TstgSubTenderFileGather.GatherSubTenderTreeNode(
  152. ANode: TsdIDTreeNode; AParent: TstgGatherTreeNode);
  153. var
  154. vCur: TstgGatherTreeNode;
  155. begin
  156. if not Assigned(ANode) then Exit;
  157. vCur := GatherSubTenderTreeNodeData(ANode, AParent);
  158. GatherSubTenderTreeNode(ANode.FirstChild, vCur);
  159. GatherSubTenderTreeNode(ANode.NextSibling, AParent);
  160. end;
  161. function TstgSubTenderFileGather.GatherSubTenderTreeNodeData(
  162. ANode: TsdIDTreeNode; AParent: TstgGatherTreeNode): TstgGatherTreeNode;
  163. var
  164. vNode: TMeasureBillsIDTreeNode;
  165. vNext: TstgGatherTreeNode;
  166. begin
  167. vNode := TMeasureBillsIDTreeNode(ANode);
  168. if ANode.ID < 100 then
  169. Result := FCacheData.GatherTree.FindNode(ANode.ID)
  170. else
  171. Result := FCacheData.GatherTree.FindNode(AParent, vNode);
  172. if not Assigned(Result) then
  173. begin
  174. vNext := FCacheData.GatherTree.FindNextSibling(AParent, vNode.Rec.Code.AsString, vNode.Rec.B_Code.AsString);
  175. if not Assigned(AParent) or (not (AParent.IsSumBase and AParent.IsLeafXmj)) or (not ANode.HasChildren) then
  176. begin
  177. if ANode.ID < 100 then
  178. Result := FCacheData.GatherTree.AddSubTenderNode(AParent, vNext, ANode.ID)
  179. else
  180. Result := FCacheData.GatherTree.AddSubTenderNode(AParent, vNext);
  181. Result.Code := Trim(vNode.Rec.Code.AsString);
  182. Result.B_Code := Trim(vNode.Rec.B_Code.AsString);
  183. Result.Name := Trim(vNode.Rec.Name.AsString);
  184. Result.Units := Trim(vNode.Rec.Units.AsString);
  185. end
  186. else
  187. Result := AParent;
  188. end;
  189. if Assigned(Result) then
  190. GatherDetailData(Result, vNode)
  191. else
  192. Result := AParent;
  193. end;
  194. procedure TstgSubTenderFileGather.GatherTo(AGatherCacheData: TstgGatherCacheData;
  195. ASubTenders: TList);
  196. var
  197. i, iSubTenderID: Integer;
  198. begin
  199. FCacheData := AGatherCacheData;
  200. for i := 0 to ASubTenders.Count - 1 do
  201. GatherSubTender(Integer(ASubTenders.Items[i]));
  202. FCacheData.GatherTree.CalculateAll;
  203. end;
  204. { TstgErrorChecker }
  205. procedure TstgErrorChecker.AddError(ANode: TstgGatherTreeNode);
  206. begin
  207. if ANode.IsGclBills then
  208. AddGclError(ANode)
  209. else
  210. AddXmjError(ANode);
  211. end;
  212. procedure TstgErrorChecker.AddGclError(ANode: TstgGatherTreeNode);
  213. begin
  214. if HasXmjChildWithSameCodeChild(ANode) then
  215. NewError(ANode, iErrorXmjLess)
  216. else if HasLongRelaCodeChild(ANode) then
  217. NewError(ANode, iErrorGclLess)
  218. else if HasShortRelaCodeChild(ANode) then
  219. NewError(ANode, iErrorGclMore)
  220. else if HasSameChildWithDiffLevel(ANode) then
  221. NewError(ANode, iErrorGclMore)
  222. else if HasSameCodeLevelChild(ANode) then
  223. NewError(ANode, iErrorGclDiff)
  224. else
  225. NewError(ANode, iErrorGclAdd);
  226. end;
  227. procedure TstgErrorChecker.AddXmjError(ANode: TstgGatherTreeNode);
  228. begin
  229. if HasSameCodeLevelChild(ANode) then
  230. NewError(ANode, iErrorXmjDiff)
  231. else
  232. NewError(ANode, iErrorXmjAdd);
  233. end;
  234. procedure TstgErrorChecker.Check(AGatherCacheData: TstgGatherCacheData);
  235. var
  236. i: Integer;
  237. vNode, vParent: TstgGatherTreeNode;
  238. begin
  239. FCacheData := AGatherCacheData;
  240. for i := 0 to FCacheData.GatherTree.CacheNodes.Count - 1 do
  241. begin
  242. vNode := TstgGatherTreeNode(FCacheData.GatherTree.CacheNodes[i]);
  243. vParent := TstgGatherTreeNode(vNode.Parent);
  244. if vNode.IsSubTender and (not Assigned(vParent) or not vParent.IsSubTender) then
  245. AddError(vNode);
  246. end;
  247. end;
  248. function TstgErrorChecker.HasLongRelaCodeChild(
  249. ANode: TstgGatherTreeNode): Boolean;
  250. var
  251. vParent, vChild: TstgGatherTreeNode;
  252. i: Integer;
  253. begin
  254. Result := False;
  255. vParent := SafeCheckParent(ANode, nil);
  256. for i := 0 to vParent.Children.Count - 1 do
  257. begin
  258. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  259. if Pos(ANode.B_Code + '-', vChild.B_Code) = 1 then
  260. begin
  261. Result := True;
  262. Break;
  263. end;
  264. end;
  265. end;
  266. function TstgErrorChecker.HasSameChildWithDiffLevel(ANode,
  267. ACheckParent: TstgGatherTreeNode): Boolean;
  268. var
  269. vParent, vChild: TstgGatherTreeNode;
  270. i: Integer;
  271. begin
  272. Result := False;
  273. vParent := SafeCheckParent(ANode, ACheckParent);
  274. for i := 0 to vParent.Children.Count - 1 do
  275. begin
  276. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  277. if vChild.IsSumBase and (vChild.Code = ANode.Code) and
  278. (vChild.B_Code = ANode.B_Code) and (vChild.Name = ANode.Name) and
  279. (vChild.Units = ANode.Units) and (vChild.IsLeaf = vChild.IsLeaf) then
  280. begin
  281. Result := True;
  282. Break;
  283. end;
  284. end;
  285. end;
  286. function TstgErrorChecker.HasSameCodeLevelChild(ANode,
  287. ACheckParent: tstgGatherTreeNode): Boolean;
  288. var
  289. vParent, vChild: TstgGatherTreeNode;
  290. i: Integer;
  291. begin
  292. Result := False;
  293. vParent := SafeCheckParent(ANode, ACheckParent);
  294. for i := 0 to vParent.Children.Count - 1 do
  295. begin
  296. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  297. if vChild.IsSumBase and (vChild.Code = ANode.Code) and (vChild.B_Code = ANode.B_Code) and (vChild.IsLeaf = vChild.IsLeaf) then
  298. begin
  299. Result := True;
  300. Break;
  301. end;
  302. end;
  303. end;
  304. function TstgErrorChecker.HasShortRelaCodeChild(
  305. ANode: TstgGatherTreeNode): Boolean;
  306. var
  307. vParent, vChild: TstgGatherTreeNode;
  308. i: Integer;
  309. begin
  310. Result := False;
  311. vParent := SafeCheckParent(ANode, nil);
  312. for i := 0 to vParent.Children.Count - 1 do
  313. begin
  314. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  315. if Pos(vChild.B_Code + '-', ANode.B_Code) = 1 then
  316. begin
  317. Result := True;
  318. Break;
  319. end;
  320. end;
  321. end;
  322. function TstgErrorChecker.HasXmjChildWithSameCodeChild(
  323. ANode: TstgGatherTreeNode): Boolean;
  324. var
  325. vParent, vChild: TstgGatherTreeNode;
  326. i: Integer;
  327. begin
  328. Result := False;
  329. vParent := SafeCheckParent(ANode, nil);
  330. for i := 0 to vParent.Children.Count - 1 do
  331. begin
  332. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  333. if not vChild.IsGclBills and ANode.IsGclBills then
  334. begin
  335. Result := True;
  336. Break;
  337. end;
  338. end;
  339. end;
  340. procedure TstgErrorChecker.NewError(ANode: TstgGatherTreeNode;
  341. AType: Integer);
  342. procedure RecursiveNewError(AParent: TstgGatherTreeNode);
  343. var
  344. i: Integer;
  345. begin
  346. if AParent.Children.Count > 0 then
  347. begin
  348. for i := 0 to AParent.Children.Count - 1 do
  349. RecursiveNewError(TstgGatherTreeNode(AParent.Children.Items[i]));
  350. end
  351. else
  352. FCacheData.AddError(ANode, AParent, AType);
  353. end;
  354. begin
  355. RecursiveNewError(ANode);
  356. end;
  357. function TstgErrorChecker.SafeCheckParent(ANode,
  358. ACheckParent: TstgGatherTreeNode): TstgGatherTreeNode;
  359. begin
  360. if Assigned(ACheckParent) then
  361. Result := ACheckParent
  362. else if Assigned(ANode.Parent) then
  363. Result := TstgGatherTreeNode(ANode.Parent)
  364. else
  365. Result := TstgGatherTreeNode(FCacheData.GatherTree.Root);
  366. end;
  367. end.