ProjectManagerDm.pas 21 KB

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