ProjectManagerDm.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. unit ProjectManagerDm;
  2. interface
  3. uses
  4. TenderBackupManager,
  5. SysUtils, Classes, DB, DBClient, Provider, ADODB, Connections, ZhAPI,
  6. sdDB, sdProvider, sdIDTree;
  7. type
  8. TProjectManagerData = class(TDataModule)
  9. sdpProjectsInfo: TsdADOProvider;
  10. sddProjectsInfo: TsdDataSet;
  11. sdvProjectsInfo: TsdDataView;
  12. sdpTenderProperty: TsdADOProvider;
  13. sddTenderProperty: TsdDataSet;
  14. sdvTenderProperty: TsdDataView;
  15. sdvProjectsSpare: TsdDataView;
  16. procedure sdvProjectsInfoGetText(var Text: String;
  17. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  18. DisplayText: Boolean);
  19. procedure sdvProjectsInfoFilterRecord(ARecord: TsdDataRecord;
  20. var Allow: Boolean);
  21. procedure DataModuleCreate(Sender: TObject);
  22. procedure sdvProjectsInfoBeforeDeleteRecord(ARecord: TsdDataRecord;
  23. var Allow: Boolean);
  24. private
  25. FConnection: TCommonConnection;
  26. FProjectsTree: TsdIDTree;
  27. procedure UpdateManagerDataBase;
  28. //procedure ReNameCurrentProject(const AName: string);
  29. procedure CreateNewProjectFile(const AName: string);
  30. procedure DeleteAllTenderFiles(ANode: TsdIDTreeNode);
  31. procedure DeleteAttachmentFiles(ANode: TsdIDTreeNode);
  32. function CreateBackupFolder(AProjectID: Integer): string;
  33. procedure ExportTender(ARec: TsdDataRecord; AFileName: string);
  34. function NewID: Integer;
  35. public
  36. constructor Create;
  37. destructor Destroy; override;
  38. procedure Open;
  39. procedure Save;
  40. function HasProject: Boolean;
  41. function ExistProject(const AName: string; ANode: TsdIDTreeNode): Boolean;
  42. function ProjectID(const AName: string; ANode: TsdIDTreeNode): Integer;
  43. // 云版要记下网络文件夹的ID和层次。
  44. function InsertProject(const AName: string; APreNode: TsdIDTreeNode; AFolderID: Integer = -1; AFolderLevel: Integer = -1): TsdIDTreeNode;
  45. function InsertSubProject(const AName: string; AParent: TsdIDTreeNode; AFolderID: Integer = -1; AFolderLevel: Integer = -1): TsdIDTreeNode;
  46. function InsertTender(const AName: string; AParent: TsdIDTreeNode): TsdIDTreeNode;
  47. procedure Delete;
  48. procedure ReName(const AName: string; ANode: TsdIDTreeNode);
  49. procedure RestoreTender(AID: Integer);
  50. procedure RefreshSeedID;
  51. procedure CalculateParentInfo(AID: Integer);
  52. function BackupPath(AProjectID: Integer): String;
  53. procedure AddOpenTenderBackup(AProjectID: Integer);
  54. procedure AddSaveTenderBackup(AProjectID: Integer);
  55. property ProjectsTree: TsdIDTree read FProjectsTree;
  56. end;
  57. implementation
  58. uses
  59. UtilMethods, UpdateDataBase, ProjectCommands, PHPWebDm, ConstUnit, Math;
  60. {$R *.dfm}
  61. { TProjectManagerData }
  62. constructor TProjectManagerData.Create;
  63. begin
  64. inherited Create(nil);
  65. FConnection := TCommonConnection.Create;
  66. FProjectsTree := TsdIDTree.Create;
  67. FProjectsTree.KeyFieldName := 'ID';
  68. FProjectsTree.ParentFieldName := 'ParentID';
  69. FProjectsTree.NextSiblingFieldName := 'NextSiblingID';
  70. FProjectsTree.AutoCreateKeyID := True;
  71. FProjectsTree.AutoExpand := True;
  72. FProjectsTree.SeedID := 1;
  73. FProjectsTree.DataView := sdvProjectsInfo;
  74. end;
  75. procedure TProjectManagerData.CreateNewProjectFile(const AName: string);
  76. var
  77. TempFolder: string;
  78. begin
  79. try
  80. TempFolder := GenerateTempFolder(GetTempFilePath);
  81. CopyFileOrFolder(GetEmptyDataBaseFileName, TempFolder + '\Main.dat');
  82. ZipFolder(TempFolder, GetMyProjectsFilePath + AName);
  83. finally
  84. DeleteFileOrFolder(TempFolder);
  85. end;
  86. end;
  87. procedure TProjectManagerData.Delete;
  88. var
  89. orgParentID: Integer;
  90. begin
  91. if HasProject then
  92. begin
  93. orgParentID := FProjectsTree.Selected.ParentID;
  94. DeleteAttachmentFiles(FProjectsTree.Selected);
  95. DeleteAllTenderFiles(FProjectsTree.Selected);
  96. FProjectsTree.DeleteNode(FProjectsTree.Selected);
  97. CalculateParentInfo(orgParentID);
  98. Save;
  99. end;
  100. end;
  101. destructor TProjectManagerData.Destroy;
  102. begin
  103. FProjectsTree.Free;
  104. FConnection.Free;
  105. inherited;
  106. end;
  107. function TProjectManagerData.ExistProject(const AName: string;
  108. ANode: TsdIDTreeNode): Boolean;
  109. var
  110. vCur: TsdIDTreeNode;
  111. begin
  112. Result := False;
  113. if not Assigned(ANode) then Exit;
  114. vCur := ANode.FirstChild;
  115. while not Result and Assigned(vCur) do
  116. begin
  117. Result := vCur.Rec.ValueByName('Name').AsString = AName;
  118. vCur := vCur.NextSibling;
  119. end;
  120. end;
  121. function TProjectManagerData.HasProject: Boolean;
  122. begin
  123. Result := sddProjectsInfo.RecordCount > 0;
  124. end;
  125. function TProjectManagerData.InsertProject(const AName: string;
  126. APreNode: TsdIDTreeNode; AFolderID: Integer; AFolderLevel: Integer): TsdIDTreeNode;
  127. var
  128. vNew: TsdIDTreeNode;
  129. bOnLine, bCanCreate: Boolean;
  130. begin
  131. // 云版判断是否已存在的标准是服务端传来的ID,不是单机版所使用的名称。
  132. // 判断条件写在这里面不合适,因为云版调用不正确,应该写到方法外面。
  133. // 现在已经这样了,改起来麻烦,先补丁的方式用着。
  134. if G_IsCloud then
  135. bCanCreate := True
  136. else if (not G_IsCloud) and (not Assigned(APreNode)
  137. or not ExistProject(AName, APreNode.Parent)) then
  138. bCanCreate := True
  139. else
  140. bCanCreate := False;
  141. if bCanCreate then
  142. begin
  143. RefreshSeedID;
  144. if Assigned(APreNode) then
  145. vNew := FProjectsTree.Add(APreNode.ParentID, APreNode.NextSiblingID)
  146. else
  147. vNew := FProjectsTree.Add(-1, -1);
  148. vNew.Rec.BeginUpdate;
  149. vNew.Rec.ValueByName('Type').AsInteger := 0;
  150. vNew.Rec.ValueByName('Name').AsString := AName;
  151. {---------------------------------------------------------------------------
  152. 恼火的问题:直接写成下面这样,则第二句编译不进:
  153. if G_IsOnLine then
  154. vNew.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
  155. 这里用局部变量bOnLine转接一下,能解决问题。
  156. ---------------------------------------------------------------------------}
  157. bOnLine := G_IsCloud;
  158. if bOnLine then
  159. begin
  160. vNew.Rec.ValueByName('WebID').AsInteger := AFolderID;
  161. vNew.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
  162. vNew.Rec.ValueByName('WebFolderLevel').AsInteger := AFolderLevel;
  163. end;
  164. vNew.Rec.EndUpdate;
  165. Result := vNew;
  166. Save;
  167. end
  168. else
  169. raise Exception.Create('存在同名类别!');
  170. end;
  171. function TProjectManagerData.InsertSubProject(const AName: string;
  172. AParent: TsdIDTreeNode; AFolderID: Integer; AFolderLevel: Integer): TsdIDTreeNode;
  173. var
  174. vNew: TsdIDTreeNode;
  175. bOnLine, bCanCreate: Boolean;
  176. begin
  177. if G_IsCloud then
  178. bCanCreate := True
  179. else if (not G_IsCloud) and (not ExistProject(AName, AParent)) then
  180. bCanCreate := True
  181. else
  182. bCanCreate := False;
  183. if bCanCreate then
  184. begin
  185. RefreshSeedID;
  186. vNew := FProjectsTree.Add(AParent.ID, -1);
  187. vNew.Rec.ValueByName('Type').AsInteger := 0;
  188. vNew.Rec.ValueByName('Name').AsString := AName;
  189. {---------------------------------------------------------------------------
  190. 恼火的问题:直接写成下面这样,则第二句编译不进:
  191. if G_IsOnLine then
  192. vNew.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
  193. 这里用局部变量bOnLine转接一下,能解决问题。
  194. ---------------------------------------------------------------------------}
  195. bOnLine := G_IsCloud;
  196. if bOnLine then
  197. begin
  198. vNew.Rec.ValueByName('WebID').AsInteger := AFolderID;
  199. vNew.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
  200. vNew.Rec.ValueByName('WebFolderLevel').AsInteger := AFolderLevel;
  201. end;
  202. Result := vNew;
  203. Save;
  204. end
  205. else
  206. raise Exception.Create('存在同名类别!');
  207. end;
  208. function TProjectManagerData.InsertTender(const AName: string;
  209. AParent: TsdIDTreeNode): TsdIDTreeNode;
  210. var bOnLine: Boolean;
  211. begin
  212. if not ExistProject(AName, AParent) then
  213. begin
  214. RefreshSeedID;
  215. Result := FProjectsTree.Add(AParent.ID, -1);
  216. {---------------------------------------------------------------------------
  217. 恼火的问题:直接写成下面这样,则第二句编译不进:
  218. if G_IsOnLine then
  219. Result.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
  220. 这里用局部变量bOnLine转接一下,能解决问题。
  221. ---------------------------------------------------------------------------}
  222. // if G_IsOnLine then
  223. // Result.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID; // 编译不进
  224. bOnLine := G_IsCloud;
  225. if bOnLine then
  226. Result.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
  227. Result.Rec.ValueByName('Type').AsInteger := 1;
  228. Result.Rec.ValueByName('Name').AsString := AName;
  229. Result.Rec.ValueByName('PhaseCount').AsInteger := 0;
  230. Result.Rec.ValueByName('AuditStatus').AsInteger := 0;
  231. Result.Rec.ValueByName('FileName').AsString :=
  232. ExtractSimpleFileName(GetNewGUIDFileName(GetMyProjectsFilePath));
  233. Result.Rec.ValueByName('CreateDate').AsString := FormatDateTime('yyyy-mm-dd', Date);
  234. CreateNewProjectFile(Result.Rec.ValueByName('FileName').AsString);
  235. Save;
  236. end
  237. else
  238. raise Exception.Create('存在同名标段!');
  239. end;
  240. procedure TProjectManagerData.Open;
  241. var
  242. sFileName: string;
  243. FQuery: TADOQuery;
  244. begin
  245. sFileName := GetAppFilePath + 'Data\ProjectManager.dat';
  246. if FileEncrypted(sFileName) then
  247. SimpleDecrypt(sFileName, sFileName);
  248. FConnection.Open(sFileName);
  249. UpdateManagerDataBase;
  250. sdpProjectsInfo.Connection := FConnection.Connection;
  251. sddProjectsInfo.Open;
  252. sdvProjectsInfo.Open;
  253. sdvProjectsSpare.Open;
  254. sddProjectsInfo.AddIndex('idxID', 'ID');
  255. sdvProjectsInfo.IndexName := 'idxID';
  256. sdpTenderProperty.Connection := FConnection.Connection;
  257. sddTenderProperty.Open;
  258. sdvTenderProperty.Open;
  259. end;
  260. procedure TProjectManagerData.Save;
  261. begin
  262. sddTenderProperty.Save;
  263. sddProjectsInfo.Save;
  264. FConnection.Save;
  265. end;
  266. procedure TProjectManagerData.UpdateManagerDataBase;
  267. var
  268. vUpdator: TUpdateManagerDB;
  269. begin
  270. vUpdator := TUpdateManagerDB.Create;
  271. try
  272. vUpdator.Update(FConnection);
  273. finally
  274. vUpdator.Free;
  275. end;
  276. end;
  277. procedure TProjectManagerData.sdvProjectsInfoGetText(var Text: String;
  278. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  279. DisplayText: Boolean);
  280. function NumToAuditStatus(AValue: Integer): string;
  281. begin
  282. case AValue of
  283. -1:
  284. if ARecord.ValueByName('PhaseCount').AsInteger = 0 then
  285. Result := '原报'
  286. else
  287. Result := '批复';
  288. 0:
  289. Result := '原报';
  290. else
  291. Result := Format('%d 审', [AValue]);
  292. end;
  293. end;
  294. function GetFormatString(ADigitValue: TsdValue): string;
  295. begin
  296. if not ADigitValue.IsNull then
  297. begin
  298. case ADigitValue.AsInteger of
  299. 0: Result := '0';
  300. 1: Result := '0.#';
  301. 2: Result := '0.##';
  302. 3: Result := '0.###';
  303. 4: Result := '0.####';
  304. 5: Result := '0.#####';
  305. 6: Result := '0.######';
  306. 7: Result := '0.#######';
  307. 8: Result := '0.########';
  308. 9: Result := '0.#########';
  309. else
  310. Result := '0.##########';
  311. end;
  312. end
  313. else
  314. Result := '';
  315. end;
  316. function FormatCommonTotalPrice(ATotalPrice: Double): string;
  317. var
  318. sFormat: string;
  319. begin
  320. Result := Text;
  321. sFormat := GetFormatString(ARecord.ValueByName('CommonDigit'));
  322. if sFormat <> '' then
  323. Result := FormatFloat(sFormat, ATotalPrice);
  324. end;
  325. function FormatDealPayTotalPrice(ATotalPrice: Double): string;
  326. var
  327. sFormat: string;
  328. begin
  329. Result := Text;
  330. sFormat := GetFormatString(ARecord.ValueByName('DealPayDigit'));
  331. if sFormat <> '' then
  332. Result := FormatFloat(sFormat, ATotalPrice);
  333. end;
  334. begin
  335. if not Assigned(ARecord) then Exit;
  336. if SameText(AColumn.FieldName, 'AuditStatus') then
  337. if ARecord.ValueByName('Type').AsInteger = 1 then
  338. Text := NumToAuditStatus(AValue.AsInteger)
  339. else
  340. Text := ''
  341. else if DisplayText then
  342. begin
  343. if Pos('TotalPrice', AColumn.FieldName) > 0 then
  344. Text := FormatCommonTotalPrice(AValue.AsFloat)
  345. else if Pos('PhasePay', AColumn.FieldName) > 0 then
  346. Text := FormatDealPayTotalPrice(AValue.AsFloat);
  347. end;
  348. end;
  349. procedure TProjectManagerData.DeleteAllTenderFiles(ANode: TsdIDTreeNode);
  350. var
  351. iChild: Integer;
  352. begin
  353. if ANode.HasChildren then
  354. for iChild := 0 to ANode.ChildCount - 1 do
  355. DeleteAllTenderFiles(ANode.ChildNodes[iChild])
  356. else if ANode.Rec.ValueByName('Type').AsInteger = 1 then
  357. DeleteFile(GetMyProjectsFilePath + ANode.Rec.ValueByName('FileName').AsString);
  358. end;
  359. procedure TProjectManagerData.ReName(const AName: string;
  360. ANode: TsdIDTreeNode);
  361. begin
  362. ANode.Rec.ValueByName('Name').AsString := AName;
  363. Save;
  364. end;
  365. procedure TProjectManagerData.RestoreTender(AID: Integer);
  366. var
  367. vNode: TsdIDTreeNode;
  368. sRestoreFile: string;
  369. Exportor: TTenderExport;
  370. begin
  371. vNode := FProjectsTree.FindNode(AID);
  372. if not FileExists(GetMyProjectsFilePath + vNode.Rec.ValueByName('FileName').AsString) then Exit;
  373. sRestoreFile := GetBackUpFilePath + vNode.Rec.ValueByName('Name').AsString
  374. + '[' + FormatDateTime('yyyy-mm-dd hh,nn,ss', Now) + '].mtf';
  375. Exportor := TTenderExport.Create(vNode.Rec, sRestoreFile);
  376. try
  377. Exportor.Execute;
  378. finally
  379. Exportor.Free;
  380. end;
  381. end;
  382. procedure TProjectManagerData.sdvProjectsInfoFilterRecord(
  383. ARecord: TsdDataRecord; var Allow: Boolean);
  384. begin
  385. if G_IsCloud then
  386. begin
  387. if ARecord.ValueByName('WebUserID').AsInteger = PHPWeb.UserID then
  388. Allow := True
  389. else
  390. Allow := False;
  391. end
  392. else
  393. begin
  394. if ARecord.ValueByName('WebUserID').AsInteger = 0 then
  395. Allow := True
  396. else
  397. Allow := False;
  398. end;
  399. end;
  400. procedure TProjectManagerData.DataModuleCreate(Sender: TObject);
  401. begin
  402. // 单机版也要过滤:防止单机版程序能显示所有用户的项目。
  403. // if G_IsOnLine then
  404. sdvProjectsInfo.Filtered := True;
  405. sdvProjectsSpare.Filtered := True;
  406. end;
  407. function TProjectManagerData.NewID: Integer;
  408. var
  409. idxID: TsdIndex;
  410. begin
  411. if sddProjectsInfo.RecordCount > 0 then
  412. begin
  413. idxID := sddProjectsInfo.FindIndex('idxID');
  414. Result := idxID.Records[idxID.RecordCount - 1].ValueByName('ID').AsInteger + 1;
  415. end
  416. else
  417. Result := 1;
  418. end;
  419. procedure TProjectManagerData.RefreshSeedID;
  420. begin
  421. FProjectsTree.SeedID := NewID;
  422. end;
  423. function TProjectManagerData.BackupPath(AProjectID: Integer): String;
  424. var
  425. Rec: TsdDataRecord;
  426. begin
  427. Result := GetAppFilePath + 'FileBackup\TenderBackup';
  428. Rec := ProjectsTree.FindNode(AProjectID).Rec;
  429. if Rec.ValueByName('BackupFolder').AsString = '' then
  430. Rec.ValueByName('BackupFolder').AsString := CreateBackupFolder(AProjectID);
  431. Result := Result + '\' + Rec.ValueByName('BackupFolder').AsString + '\';
  432. end;
  433. function TProjectManagerData.CreateBackupFolder(
  434. AProjectID: Integer): string;
  435. function GetParentNames(ANode: TsdIDTreeNode): string;
  436. var
  437. stnParent: TsdIDTreeNode;
  438. begin
  439. Result := '';
  440. stnParent := ANode.Parent;
  441. while Assigned(stnParent) do
  442. begin
  443. if Result <> '' then
  444. Result := stnParent.Rec.ValueByName('Name').AsString + '--' + Result
  445. else
  446. Result := stnParent.Rec.ValueByName('Name').AsString;
  447. stnParent := stnParent.Parent;
  448. end;
  449. end;
  450. var
  451. stnNode: TsdIDTreeNode;
  452. sGUID, sPath: string;
  453. sgs: TStringList;
  454. begin
  455. stnNode := ProjectsTree.FindNode(AProjectID);
  456. Result := stnNode.Rec.ValueByName('BackupFolder').AsString;
  457. if Result <> '' then Exit;
  458. sPath := GetAppFilePath + 'FileBackup\TenderBackup\';
  459. sGUID := GetNewGUIDFileName(sPath);
  460. if FileExists(sGUID) then DeleteFile(sGUID);
  461. CreateDirectoryInDeep(sGUID);
  462. sgs := TStringList.Create;
  463. try
  464. sgs.Add('项目备份文件夹');
  465. sgs.Add(Format('项目名称:%s', [stnNode.Rec.ValueByName('Name').AsString]));
  466. sgs.Add(Format('所属项目:%s', [GetParentNames(stnNode)]));
  467. sgs.Add(Format('创建时间:%s', [DateTimeToStr(Now)]));
  468. finally
  469. sgs.SaveToFile(sGUID + '\说明.txt');
  470. sgs.Free;
  471. end;
  472. Result := ExtractSimpleFileName(sGUID)
  473. end;
  474. procedure TProjectManagerData.sdvProjectsInfoBeforeDeleteRecord(
  475. ARecord: TsdDataRecord; var Allow: Boolean);
  476. var
  477. sOrgFolder, sNewFolder: string;
  478. begin
  479. if ARecord.ValueByName('BackupFolder').AsString <> '' then
  480. begin
  481. sOrgFolder := GetAppFilePath + 'FileBackup\TenderBackup\'
  482. + ARecord.ValueByName('BackupFolder').AsString;
  483. sNewFolder := GetAppFilePath + 'FileBackup\RecycleBackup\'
  484. + ARecord.ValueByName('BackupFolder').AsString;
  485. CopyFileOrFolder(sOrgFolder, sNewFolder);
  486. DeleteFileOrFolder(sOrgFolder);
  487. end;
  488. end;
  489. procedure TProjectManagerData.AddOpenTenderBackup(AProjectID: Integer);
  490. var
  491. vBackupManager: TBackupManager;
  492. BackupRec, Rec: TsdDataRecord;
  493. sBackupFile: string;
  494. begin
  495. Rec := sddProjectsInfo.FindKey('idxID', AProjectID);
  496. if not Assigned(Rec) then Exit;
  497. vBackupManager := TBackupManager.Create;
  498. try
  499. vBackupManager.LoadBackupFile(BackupPath(AProjectID));
  500. if vBackupManager.LastestOpenBackupIsToday then Exit;
  501. sBackupFile := vBackupManager.OpenBackupFile;
  502. if FileExists(sBackupFile) then DeleteFile(sBackupFile);
  503. ExportTender(Rec, sBackupFile);
  504. finally
  505. vBackupManager.Free;
  506. end;
  507. end;
  508. procedure TProjectManagerData.AddSaveTenderBackup(AProjectID: Integer);
  509. var
  510. vBackupManager: TBackupManager;
  511. BackupRec, Rec: TsdDataRecord;
  512. sBackupFile: string;
  513. begin
  514. Rec := sddProjectsInfo.FindKey('idxID', AProjectID);
  515. if not Assigned(Rec) then Exit;
  516. vBackupManager := TBackupManager.Create;
  517. try
  518. vBackupManager.LoadBackupFile(BackupPath(AProjectID));
  519. sBackupFile := vBackupManager.SaveBackupFile;
  520. if FileExists(sBackupFile) then DeleteFile(sBackupFile);
  521. ExportTender(Rec, sBackupFile);
  522. finally
  523. vBackupManager.Free;
  524. end;
  525. end;
  526. procedure TProjectManagerData.ExportTender(ARec: TsdDataRecord;
  527. AFileName: string);
  528. var
  529. Exportor : TTenderExport;
  530. begin
  531. Exportor := TTenderExport.Create(ARec, AFileName);
  532. try
  533. Exportor.Execute;
  534. finally
  535. Exportor.Free;
  536. end;
  537. end;
  538. function TProjectManagerData.ProjectID(const AName: string;
  539. ANode: TsdIDTreeNode): Integer;
  540. var
  541. vCur: TsdIDTreeNode;
  542. begin
  543. Result := -1;
  544. if not Assigned(ANode) then Exit;
  545. vCur := ANode.FirstChild;
  546. while (Result = -1) and Assigned(vCur) do
  547. begin
  548. if vCur.Rec.ValueByName('Name').AsString = AName then
  549. Result := vCur.ID;
  550. vCur := vCur.NextSibling;
  551. end;
  552. end;
  553. procedure TProjectManagerData.DeleteAttachmentFiles(ANode: TsdIDTreeNode);
  554. var sDir: string;
  555. procedure DeleteAtch(ANode: TsdIDTreeNode);
  556. begin
  557. // 如果文件名为空,删除时会删除整个附件文件夹,危险!
  558. if ANode.Rec.ValueByName('FileName').AsString = '' then Exit;
  559. sDir := GetMyProjectsFilePath + 'Attachment\' + ANode.Rec.ValueByName('FileName').AsString;
  560. DeleteFolder(sDir);
  561. end;
  562. procedure DeleteNodes(ANode: TsdIDTreeNode);
  563. begin
  564. if ANode = nil then Exit;
  565. if ANode.FirstChild <> nil then
  566. DeleteNodes(ANode.FirstChild);
  567. if ANode.Rec.ValueByName('Type').AsInteger = 1 then
  568. DeleteAtch(ANode);
  569. if ANode.NextSibling <> nil then
  570. DeleteNodes(ANode.NextSibling);
  571. end;
  572. begin
  573. if not G_IsCloud then
  574. begin
  575. if not Assigned(ANode) then Exit;
  576. if ANode.Rec.ValueByName('Type').AsInteger = 0 then
  577. begin
  578. if Assigned(ANode.FirstChild) then
  579. DeleteNodes(ANode.FirstChild);
  580. end
  581. else
  582. DeleteAtch(ANode);
  583. end;
  584. end;
  585. procedure TProjectManagerData.CalculateParentInfo(AID: Integer);
  586. procedure ResetDigit(ANode: TsdIDTreeNode);
  587. var
  588. iChild, iCommonDigit, iDealPayDigit: Integer;
  589. vChild: TsdIDTreeNode;
  590. begin
  591. iCommonDigit := 0;
  592. iDealPayDigit := 0;
  593. for iChild := 0 to ANode.ChildCount - 1 do
  594. begin
  595. vChild := ANode.ChildNodes[iChild];
  596. iCommonDigit := Max(iCommonDigit, vChild.Rec.ValueByName('CommonDigit').AsInteger);
  597. iDealPayDigit := Max(iDealPayDigit, vChild.Rec.ValueByName('DealPayDigit').AsInteger);
  598. end;
  599. ANode.Rec.ValueByName('CommonDigit').AsInteger := iCommonDigit;
  600. ANode.Rec.ValueByName('DealPayDigit').AsInteger := iDealPayDigit;
  601. end;
  602. procedure ReCalculateInfo(ANode: TsdIDTreeNode);
  603. var
  604. fDeal, fDeal_BGL, fPhase, fEndDeal, fEndChange, fEnd, fPre, fPhasePay, fEndPhasePay: Double;
  605. iChild, iCommonDigit, iDealPayDigit: Integer;
  606. vChild: TsdIDTreeNode;
  607. begin
  608. fDeal := 0;
  609. fDeal_BGL := 0;
  610. fPhase := 0;
  611. fEndDeal := 0;
  612. fEndChange := 0;
  613. fEnd := 0;
  614. fPre := 0;
  615. fPhasePay := 0;
  616. fEndPhasePay := 0;
  617. iCommonDigit := - ANode.Rec.ValueByName('CommonDigit').AsInteger;
  618. iDealPayDigit := - ANode.Rec.ValueByName('DealPayDigit').AsInteger;
  619. for iChild := 0 to ANode.ChildCount - 1 do
  620. begin
  621. vChild := ANode.ChildNodes[iChild];
  622. fDeal := fDeal + vChild.Rec.ValueByName('DealTotalPrice').AsFloat;
  623. fDeal_BGL := fDeal_BGL + vChild.Rec.ValueByName('Deal_BGLTotalPrice').AsFloat;
  624. fPhase := fPhase + vChild.Rec.ValueByName('PhaseTotalPrice').AsFloat;
  625. fEndDeal := fEndDeal + vChild.Rec.ValueByName('EndDealTotalPrice').AsFloat;
  626. fEndChange := fEndChange + vChild.Rec.ValueByName('EndChangeTotalPrice').AsFloat;
  627. fEnd := fEnd + vChild.Rec.ValueByName('EndTotalPrice').AsFloat;
  628. fPre := fPre + vChild.Rec.ValueByName('PreTotalPrice').AsFloat;
  629. fPhasePay := fPhasePay + vChild.Rec.ValueByName('PhasePay').AsFloat;
  630. fEndPhasePay := fEndPhasePay + vChild.Rec.ValueByName('EndPhasePay').AsFloat;
  631. end;
  632. ANode.Rec.ValueByName('DealTotalPrice').AsFloat := CommonRoundTo(fDeal, iCommonDigit);
  633. ANode.Rec.ValueByName('Deal_BGLTotalPrice').AsFloat := CommonRoundTo(fDeal_BGL, iCommonDigit);
  634. ANode.Rec.ValueByName('PhaseTotalPrice').AsFloat := CommonRoundTo(fPhase, iCommonDigit);
  635. ANode.Rec.ValueByName('EndDealTotalPrice').AsFloat := CommonRoundTo(fEndDeal, iCommonDigit);
  636. ANode.Rec.ValueByName('EndChangeTotalPrice').AsFloat := CommonRoundTo(fEndChange, iCommonDigit);
  637. ANode.Rec.ValueByName('EndTotalPrice').AsFloat := CommonRoundTo(fEnd, iCommonDigit);
  638. ANode.Rec.ValueByName('PreTotalPrice').AsFloat := CommonRoundTo(fPre, iCommonDigit);
  639. ANode.Rec.ValueByName('PhasePay').AsFloat := CommonRoundTo(fPhasePay, iDealPayDigit);
  640. ANode.Rec.ValueByName('EndPhasePay').AsFloat := CommonRoundTo(fEndPhasePay, iDealPayDigit);
  641. end;
  642. var
  643. vNode, vChild: TsdIDTreeNode;
  644. iChild: Integer;
  645. begin
  646. if AID = -1 then Exit;
  647. vNode := ProjectsTree.FindNode(AID);
  648. if (not Assigned(vNode)) or (vNode.Rec.ValueByName('Type').AsInteger = 1) then Exit;
  649. ResetDigit(vNode);
  650. ReCalculateInfo(vNode);
  651. CalculateParentInfo(vNode.ParentID);
  652. end;
  653. end.