stgGather.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  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. if not Assigned(AParent) or (not (AParent.IsSumBase and AParent.IsLeafXmj)) or (not ANode.HasChildren) then
  175. begin
  176. if ANode.ID < 100 then
  177. Result := FCacheData.GatherTree.AddSubTenderNode(AParent, nil, ANode.ID)
  178. else
  179. Result := FCacheData.GatherTree.AddSubTenderNode(AParent, nil);
  180. Result.Code := vNode.Rec.Code.AsString;
  181. Result.B_Code := vNode.Rec.B_Code.AsString;
  182. Result.Name := vNode.Rec.Name.AsString;
  183. Result.Units := vNode.Rec.Units.AsString
  184. end
  185. else
  186. Result := AParent;
  187. end;
  188. if Assigned(Result) then
  189. GatherDetailData(Result, vNode)
  190. else
  191. Result := AParent;
  192. end;
  193. procedure TstgSubTenderFileGather.GatherTo(AGatherCacheData: TstgGatherCacheData;
  194. ASubTenders: TList);
  195. var
  196. i, iSubTenderID: Integer;
  197. begin
  198. FCacheData := AGatherCacheData;
  199. for i := 0 to ASubTenders.Count - 1 do
  200. GatherSubTender(Integer(ASubTenders.Items[i]));
  201. FCacheData.GatherTree.CalculateAll;
  202. end;
  203. { TstgErrorChecker }
  204. procedure TstgErrorChecker.AddError(ANode: TstgGatherTreeNode);
  205. begin
  206. if ANode.IsGclBills then
  207. AddGclError(ANode)
  208. else
  209. AddXmjError(ANode);
  210. end;
  211. procedure TstgErrorChecker.AddGclError(ANode: TstgGatherTreeNode);
  212. begin
  213. if HasXmjChildWithSameCodeChild(ANode) then
  214. NewError(ANode, iErrorXmjLess)
  215. else if HasLongRelaCodeChild(ANode) then
  216. NewError(ANode, iErrorGclLess)
  217. else if HasShortRelaCodeChild(ANode) then
  218. NewError(ANode, iErrorGclMore)
  219. else if HasSameChildWithDiffLevel(ANode) then
  220. NewError(ANode, iErrorGclMore)
  221. else if HasSameCodeLevelChild(ANode) then
  222. NewError(ANode, iErrorGclDiff)
  223. else
  224. NewError(ANode, iErrorGclAdd);
  225. end;
  226. procedure TstgErrorChecker.AddXmjError(ANode: TstgGatherTreeNode);
  227. begin
  228. if HasSameCodeLevelChild(ANode) then
  229. NewError(ANode, iErrorXmjDiff)
  230. else
  231. NewError(ANode, iErrorXmjAdd);
  232. end;
  233. procedure TstgErrorChecker.Check(AGatherCacheData: TstgGatherCacheData);
  234. var
  235. i: Integer;
  236. vNode, vParent: TstgGatherTreeNode;
  237. begin
  238. FCacheData := AGatherCacheData;
  239. for i := 0 to FCacheData.GatherTree.CacheNodes.Count - 1 do
  240. begin
  241. vNode := TstgGatherTreeNode(FCacheData.GatherTree.CacheNodes[i]);
  242. vParent := TstgGatherTreeNode(vNode.Parent);
  243. if vNode.IsSubTender and (not Assigned(vParent) or not vParent.IsSubTender) then
  244. AddError(vNode);
  245. end;
  246. end;
  247. function TstgErrorChecker.HasLongRelaCodeChild(
  248. ANode: TstgGatherTreeNode): Boolean;
  249. var
  250. vParent, vChild: TstgGatherTreeNode;
  251. i: Integer;
  252. begin
  253. Result := False;
  254. vParent := SafeCheckParent(ANode, nil);
  255. for i := 0 to vParent.Children.Count - 1 do
  256. begin
  257. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  258. if Pos(ANode.B_Code + '-', vChild.B_Code) = 1 then
  259. begin
  260. Result := True;
  261. Break;
  262. end;
  263. end;
  264. end;
  265. function TstgErrorChecker.HasSameChildWithDiffLevel(ANode,
  266. ACheckParent: TstgGatherTreeNode): Boolean;
  267. var
  268. vParent, vChild: TstgGatherTreeNode;
  269. i: Integer;
  270. begin
  271. Result := False;
  272. vParent := SafeCheckParent(ANode, ACheckParent);
  273. for i := 0 to vParent.Children.Count - 1 do
  274. begin
  275. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  276. if vChild.IsSumBase and (vChild.Code = ANode.Code) and
  277. (vChild.B_Code = ANode.B_Code) and (vChild.Name = ANode.Name) and
  278. (vChild.Units = ANode.Units) and (vChild.IsLeaf = vChild.IsLeaf) then
  279. begin
  280. Result := True;
  281. Break;
  282. end;
  283. end;
  284. end;
  285. function TstgErrorChecker.HasSameCodeLevelChild(ANode,
  286. ACheckParent: tstgGatherTreeNode): Boolean;
  287. var
  288. vParent, vChild: TstgGatherTreeNode;
  289. i: Integer;
  290. begin
  291. Result := False;
  292. vParent := SafeCheckParent(ANode, ACheckParent);
  293. for i := 0 to vParent.Children.Count - 1 do
  294. begin
  295. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  296. if vChild.IsSumBase and (vChild.Code = ANode.Code) and (vChild.B_Code = ANode.B_Code) and (vChild.IsLeaf = vChild.IsLeaf) then
  297. begin
  298. Result := True;
  299. Break;
  300. end;
  301. end;
  302. end;
  303. function TstgErrorChecker.HasShortRelaCodeChild(
  304. ANode: TstgGatherTreeNode): Boolean;
  305. var
  306. vParent, vChild: TstgGatherTreeNode;
  307. i: Integer;
  308. begin
  309. Result := False;
  310. vParent := SafeCheckParent(ANode, nil);
  311. for i := 0 to vParent.Children.Count - 1 do
  312. begin
  313. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  314. if Pos(vChild.B_Code + '-', ANode.B_Code) = 1 then
  315. begin
  316. Result := True;
  317. Break;
  318. end;
  319. end;
  320. end;
  321. function TstgErrorChecker.HasXmjChildWithSameCodeChild(
  322. ANode: TstgGatherTreeNode): Boolean;
  323. var
  324. vParent, vChild: TstgGatherTreeNode;
  325. i: Integer;
  326. begin
  327. Result := False;
  328. vParent := SafeCheckParent(ANode, nil);
  329. for i := 0 to vParent.Children.Count - 1 do
  330. begin
  331. vChild := TstgGatherTreeNode(vParent.Children.Items[i]);
  332. if not vChild.IsGclBills and ANode.IsGclBills then
  333. begin
  334. Result := True;
  335. Break;
  336. end;
  337. end;
  338. end;
  339. procedure TstgErrorChecker.NewError(ANode: TstgGatherTreeNode;
  340. AType: Integer);
  341. procedure RecursiveNewError(AParent: TstgGatherTreeNode);
  342. var
  343. i: Integer;
  344. begin
  345. if AParent.Children.Count > 0 then
  346. begin
  347. for i := 0 to AParent.Children.Count - 1 do
  348. RecursiveNewError(TstgGatherTreeNode(AParent.Children.Items[i]));
  349. end
  350. else
  351. FCacheData.AddError(ANode, AParent, AType);
  352. end;
  353. begin
  354. RecursiveNewError(ANode);
  355. end;
  356. function TstgErrorChecker.SafeCheckParent(ANode,
  357. ACheckParent: TstgGatherTreeNode): TstgGatherTreeNode;
  358. begin
  359. if Assigned(ACheckParent) then
  360. Result := ACheckParent
  361. else if Assigned(ANode.Parent) then
  362. Result := TstgGatherTreeNode(ANode.Parent)
  363. else
  364. Result := TstgGatherTreeNode(FCacheData.GatherTree.Root);
  365. end;
  366. end.