stgGather.pas 13 KB

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