ProjectManagerDm.pas 21 KB

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