stgGather.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. Result.IsLeaf := not ANode.HasChildren;
  119. end;
  120. { TstgSubTenderFileGather }
  121. procedure TstgSubTenderFileGather.GatherDetailData(
  122. AGatherNode: TstgGatherTreeNode; ASourceNode: TMeasureBillsIDTreeNode);
  123. var
  124. vSubTender: TstgSubTenderStageData;
  125. begin
  126. //if Assigned(ASourceNode.StageRec) and
  127. // ((ASourceNode.StageRec.GatherQuantity.AsFloat <> 0) or (ASourceNode.StageRec.GatherTotalPrice.AsFloat <> 0)) then
  128. //if not ASourceNode.HasChildren then
  129. if (AGatherNode.IsSubTender) or (not ASourceNode.HasChildren) then
  130. begin
  131. vSubTender := AGatherNode.SafeSubTender(FCurSubTenderID);
  132. vSubTender.AddDetail(ASourceNode);
  133. end;
  134. end;
  135. procedure TstgSubTenderFileGather.GatherSubTender(ASubTenderID: Integer);
  136. var
  137. vNode: TsdIDTreeNode;
  138. begin
  139. FCurSubTenderID := ASubTenderID;
  140. vNode := ProjectManager.ProjectsTree.FindNode(ASubTenderID);
  141. if vNode.Rec.ValueByName('Type').AsInteger = 1 then
  142. begin;
  143. FProjectData := OpenProjectManager.FindProjectData(ASubTenderID);
  144. try
  145. if not Assigned(FProjectData) then
  146. begin
  147. FProjectData := TProjectData.Create;
  148. FProjectData.OpenForSumUpGather(GetMyProjectsFilePath + vNode.Rec.ValueByName('FileName').AsString);
  149. end;
  150. FCacheData.AddSubTender(vNode.Rec);
  151. GatherSubTenderTreeNode(FProjectData.BillsMeasureData.BillsMeasureTree.FirstNode, nil);
  152. finally
  153. if not Assigned(OpenProjectManager.FindProjectData(ASubTenderID)) then
  154. FProjectData.Free;
  155. end;
  156. end;
  157. end;
  158. procedure TstgSubTenderFileGather.GatherSubTenderTreeNode(
  159. ANode: TsdIDTreeNode; AParent: TstgGatherTreeNode);
  160. var
  161. vCur: TstgGatherTreeNode;
  162. begin
  163. if not Assigned(ANode) then Exit;
  164. vCur := GatherSubTenderTreeNodeData(ANode, AParent);
  165. GatherSubTenderTreeNode(ANode.FirstChild, vCur);
  166. GatherSubTenderTreeNode(ANode.NextSibling, AParent);
  167. end;
  168. function TstgSubTenderFileGather.GatherSubTenderTreeNodeData(
  169. ANode: TsdIDTreeNode; AParent: TstgGatherTreeNode): TstgGatherTreeNode;
  170. var
  171. vNode: TMeasureBillsIDTreeNode;
  172. vNext: TstgGatherTreeNode;
  173. begin
  174. vNode := TMeasureBillsIDTreeNode(ANode);
  175. if ANode.ID < 100 then
  176. Result := FCacheData.GatherTree.FindNode(ANode.ID)
  177. else
  178. Result := FCacheData.GatherTree.FindNode(AParent, vNode);
  179. if not Assigned(Result) then
  180. begin
  181. vNext := FCacheData.GatherTree.FindNextSibling(AParent, vNode.Rec.Code.AsString, vNode.Rec.B_Code.AsString);
  182. if not Assigned(AParent) or (not (AParent.IsSumBase and AParent.IsLeafXmj)) or (vNode.Rec.B_Code.AsString <> '') {or (not ANode.HasChildren)} then
  183. begin
  184. if ANode.ID < 100 then
  185. Result := FCacheData.GatherTree.AddSubTenderNode(AParent, vNext, ANode.ID)
  186. else
  187. Result := FCacheData.GatherTree.AddSubTenderNode(AParent, vNext);
  188. Result.Code := Trim(vNode.Rec.Code.AsString);
  189. Result.B_Code := Trim(vNode.Rec.B_Code.AsString);
  190. Result.Name := Trim(vNode.Rec.Name.AsString);
  191. Result.Units := Trim(vNode.Rec.Units.AsString);
  192. Result.IsLeaf := not vNode.HasChildren;
  193. end
  194. else
  195. Result := AParent;
  196. end;
  197. if Assigned(Result) then
  198. GatherDetailData(Result, vNode)
  199. else
  200. Result := AParent;
  201. end;
  202. procedure TstgSubTenderFileGather.GatherTo(AGatherCacheData: TstgGatherCacheData;
  203. ASubTenders: TList);
  204. var
  205. i, iSubTenderID: Integer;
  206. begin
  207. FCacheData := AGatherCacheData;
  208. for i := 0 to ASubTenders.Count - 1 do
  209. GatherSubTender(Integer(ASubTenders.Items[i]));
  210. FCacheData.GatherTree.CalculateAll;
  211. end;
  212. { TstgErrorChecker }
  213. procedure TstgErrorChecker.AddError(ANode: TstgGatherTreeNode);
  214. begin
  215. if ANode.IsGclBills then
  216. AddGclError(ANode)
  217. else
  218. AddXmjError(ANode);
  219. end;
  220. procedure TstgErrorChecker.AddGclError(ANode: TstgGatherTreeNode);
  221. begin
  222. if HasXmjChildWithSameCodeChild(ANode) then
  223. NewError(ANode, iErrorXmjLess)
  224. else if HasLongRelaCodeChild(ANode) then
  225. NewError(ANode, iErrorGclMore)
  226. else if HasShortRelaCodeChild(ANode) then
  227. NewError(ANode, iErrorGclLess)
  228. else if HasSameChildWithDiffLevel(ANode) then
  229. NewError(ANode, iErrorGclMore)
  230. else if HasSameCodeLevelChild(ANode) then
  231. NewError(ANode, iErrorGclDiff)
  232. else
  233. NewError(ANode, iErrorGclAdd);
  234. end;
  235. procedure TstgErrorChecker.AddXmjError(ANode: TstgGatherTreeNode);
  236. begin
  237. if HasSameCodeLevelChild(ANode) then
  238. NewError(ANode, iErrorXmjDiff)
  239. else
  240. NewError(ANode, iErrorXmjAdd);
  241. end;
  242. procedure TstgErrorChecker.Check(AGatherCacheData: TstgGatherCacheData);
  243. var
  244. i: Integer;
  245. vNode, vParent: TstgGatherTreeNode;
  246. begin
  247. FCacheData := AGatherCacheData;
  248. for i := 0 to FCacheData.GatherTree.CacheNodes.Count - 1 do
  249. begin
  250. vNode := TstgGatherTreeNode(FCacheData.GatherTree.CacheNodes[i]);
  251. vParent := TstgGatherTreeNode(vNode.Parent);
  252. if vNode.IsSubTender and (not Assigned(vParent) or not vParent.IsSubTender) then
  253. AddError(vNode);
  254. end;
  255. end;
  256. function TstgErrorChecker.HasLongRelaCodeChild(
  257. ANode: TstgGatherTreeNode): Boolean;
  258. var
  259. vParent, vChild: TstgGatherTreeNode;
  260. i: Integer;
  261. begin
  262. Result := False;
  263. vParent := SafeCheckParent(ANode, nil);
  264. for i := 0 to vParent.Children.Count - 1 do
  265. begin
  266. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  267. if (Pos(ANode.B_Code + '-', vChild.B_Code) = 1) and (vChild.IsSumBase) then
  268. begin
  269. Result := True;
  270. Break;
  271. end;
  272. end;
  273. end;
  274. function TstgErrorChecker.HasSameChildWithDiffLevel(ANode,
  275. ACheckParent: TstgGatherTreeNode): Boolean;
  276. var
  277. vParent, vChild: TstgGatherTreeNode;
  278. i: Integer;
  279. begin
  280. Result := False;
  281. vParent := SafeCheckParent(ANode, ACheckParent);
  282. for i := 0 to vParent.Children.Count - 1 do
  283. begin
  284. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  285. if vChild.IsSumBase and (vChild.Code = ANode.Code) and
  286. (vChild.B_Code = ANode.B_Code) and (vChild.Name = ANode.Name) and
  287. (vChild.Units = ANode.Units) and (vChild.IsLeaf = vChild.IsLeaf) then
  288. begin
  289. Result := True;
  290. Break;
  291. end;
  292. end;
  293. end;
  294. function TstgErrorChecker.HasSameCodeLevelChild(ANode,
  295. ACheckParent: tstgGatherTreeNode): Boolean;
  296. var
  297. vParent, vChild: TstgGatherTreeNode;
  298. i: Integer;
  299. begin
  300. Result := False;
  301. vParent := SafeCheckParent(ANode, ACheckParent);
  302. for i := 0 to vParent.Children.Count - 1 do
  303. begin
  304. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  305. if vChild.IsSumBase and (vChild.Code = ANode.Code) and (vChild.B_Code = ANode.B_Code) and (vChild.IsLeaf = vChild.IsLeaf) then
  306. begin
  307. Result := True;
  308. Break;
  309. end;
  310. end;
  311. end;
  312. function TstgErrorChecker.HasShortRelaCodeChild(
  313. ANode: TstgGatherTreeNode): Boolean;
  314. var
  315. vParent, vChild: TstgGatherTreeNode;
  316. i: Integer;
  317. begin
  318. Result := False;
  319. vParent := SafeCheckParent(ANode, nil);
  320. for i := 0 to vParent.Children.Count - 1 do
  321. begin
  322. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  323. if (Pos(vChild.B_Code + '-', ANode.B_Code) = 1) and (vChild.IsSumBase) then
  324. begin
  325. Result := True;
  326. Break;
  327. end;
  328. end;
  329. end;
  330. function TstgErrorChecker.HasXmjChildWithSameCodeChild(
  331. ANode: TstgGatherTreeNode): Boolean;
  332. var
  333. vParent, vChild: TstgGatherTreeNode;
  334. i: Integer;
  335. begin
  336. Result := False;
  337. vParent := SafeCheckParent(ANode, nil);
  338. for i := 0 to vParent.Children.Count - 1 do
  339. begin
  340. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  341. if not vChild.IsGclBills and ANode.IsGclBills and vChild.IsSumBase then
  342. begin
  343. Result := True;
  344. Break;
  345. end;
  346. end;
  347. end;
  348. procedure TstgErrorChecker.NewError(ANode: TstgGatherTreeNode;
  349. AType: Integer);
  350. procedure RecursiveNewError(AParent: TstgGatherTreeNode);
  351. var
  352. i: Integer;
  353. begin
  354. if AParent.Children.Count > 0 then
  355. begin
  356. for i := 0 to AParent.Children.Count - 1 do
  357. RecursiveNewError(TstgGatherTreeNode(AParent.Children.Items[i]));
  358. end
  359. else
  360. FCacheData.AddError(ANode, AParent, AType);
  361. end;
  362. begin
  363. RecursiveNewError(ANode);
  364. end;
  365. function TstgErrorChecker.SafeCheckParent(ANode,
  366. ACheckParent: TstgGatherTreeNode): TstgGatherTreeNode;
  367. begin
  368. if Assigned(ACheckParent) then
  369. Result := ACheckParent
  370. else if Assigned(ANode.Parent) then
  371. Result := TstgGatherTreeNode(ANode.Parent)
  372. else
  373. Result := TstgGatherTreeNode(FCacheData.GatherTree.Root);
  374. end;
  375. end.