瀏覽代碼

上报、审核、批复过程中添加文件校验,仅在检验正确的情况下才生产文件

MaiXinRong 9 年之前
父節點
當前提交
0457acf485
共有 5 個文件被更改,包括 147 次插入48 次删除
  1. 12 2
      Forms/MainFrm.pas
  2. 3 2
      Frames/ProjectManagerFme.pas
  3. 101 31
      Units/ProjectCommands.pas
  4. 23 10
      Units/ProjectData.pas
  5. 8 3
      Units/UtilMethods.pas

+ 12 - 2
Forms/MainFrm.pas

@@ -549,7 +549,12 @@ begin
   try
   try
     CurProjectFrame.ProjectData.Save;
     CurProjectFrame.ProjectData.Save;
     {$O-}
     {$O-}
-      CurProjectFrame.ProjectData.ReplyProject;
+      // 失败后重复一次
+      if not CurProjectFrame.ProjectData.ReplyProject then
+      begin
+        if not CurProjectFrame.ProjectData.ReplyProject then
+          ErrorMessage('批复项目失败!');
+      end;
     {$O+}
     {$O+}
   finally
   finally
     Screen.Cursor := crDefault;
     Screen.Cursor := crDefault;
@@ -564,7 +569,12 @@ begin
   try
   try
     CurProjectFrame.ProjectData.Save;
     CurProjectFrame.ProjectData.Save;
     {$O-}
     {$O-}
-      CurProjectFrame.ProjectData.SubmitProject;
+      // 失败后重复一次
+      if not CurProjectFrame.ProjectData.SubmitProject then
+      begin
+        if not CurProjectFrame.ProjectData.SubmitProject then
+          ErrorMessage('上报项目失败!');
+      end;
     {$O+}
     {$O+}
   finally
   finally
     Screen.Cursor := crDefault;
     Screen.Cursor := crDefault;

+ 3 - 2
Frames/ProjectManagerFme.pas

@@ -328,10 +328,11 @@ var
               // 导入更新-------------------------------------------------------
               // 导入更新-------------------------------------------------------
 
 
               // 导入前须检测无锁文件中仅含有原报数据
               // 导入前须检测无锁文件中仅含有原报数据
-              vFileCheck := TTenderFileChecker.Create(sLocalFile);
+              vFileCheck := TTenderFileChecker.Create;
               try
               try
                 // 有一期以上数据,且最新期数据审核状态为原报
                 // 有一期以上数据,且最新期数据审核状态为原报
-                bCanImp := (vFileCheck.PhaseCount > 0) and (vFileCheck.AuditStatus = 0);
+                bCanImp := vFileCheck.CheckFileValid(sLocalFile)
+                    and (vFileCheck.PhaseCount > 0) and (vFileCheck.AuditStatus = 0);
                 if not bCanImp then
                 if not bCanImp then
                 begin
                 begin
                   Application.MessageBox(PChar('已从云端下载原报上传的无锁文件到本地,但文件有错误,禁止导入!请致电纵横服务人员以获取帮助。'), '警告', MB_OK + MB_ICONWARNING);
                   Application.MessageBox(PChar('已从云端下载原报上传的无锁文件到本地,但文件有错误,禁止导入!请致电纵横服务人员以获取帮助。'), '警告', MB_OK + MB_ICONWARNING);

+ 101 - 31
Units/ProjectCommands.pas

@@ -36,6 +36,8 @@ type
     procedure SaveInfoToXmlDocument(AXmlNode: IXMLNode);
     procedure SaveInfoToXmlDocument(AXmlNode: IXMLNode);
     procedure ExportXmlInfo;
     procedure ExportXmlInfo;
     function GetNewOutputFileName: string;
     function GetNewOutputFileName: string;
+
+    function CheckFile(const AFileName: string): Boolean;
   protected
   protected
     procedure OpenProject; virtual;
     procedure OpenProject; virtual;
     procedure SaveProject; virtual;
     procedure SaveProject; virtual;
@@ -43,8 +45,8 @@ type
     constructor Create(const AProjectName, AFileName: string; AProjectID: Integer);
     constructor Create(const AProjectName, AFileName: string; AProjectID: Integer);
     destructor Destroy; override;
     destructor Destroy; override;
 
 
-    procedure Execute; virtual;
-    procedure ExportTo(AFileName: string); virtual;
+    function Execute: Boolean; virtual;
+    function ExportTo(AFileName: string): Boolean; virtual;
   end;
   end;
 
 
   TSubmitProject = class(TReportBase)
   TSubmitProject = class(TReportBase)
@@ -52,8 +54,8 @@ type
     procedure OpenProject; override;
     procedure OpenProject; override;
     procedure SaveProject; override;
     procedure SaveProject; override;
   public
   public
-    procedure Execute; override;
-    procedure ExportTo(AFileName: string); override;
+    function Execute: Boolean; override;
+    function ExportTo(AFileName: string): Boolean; override;
   end;
   end;
 
 
   TReplyProject = class(TReportBase)
   TReplyProject = class(TReportBase)
@@ -61,8 +63,8 @@ type
     procedure OpenProject; override;
     procedure OpenProject; override;
     procedure SaveProject; override;
     procedure SaveProject; override;
   public
   public
-    procedure Execute; override;
-    procedure ExportTo(AFileName: string); override;
+    function Execute: Boolean; override;
+    function ExportTo(AFileName: string): Boolean; override;
   end;
   end;
 
 
   {1. 生成临时文件夹
   {1. 生成临时文件夹
@@ -224,10 +226,27 @@ type
     procedure Execute;
     procedure Execute;
   end;
   end;
 
 
+  // 文件检验
+  {
+    检验分为两部分:
+    1. 一致性检验:检验文件中的xml记录数据,与数据库中数据是否一致,以检验文件是否可用
+    2. 主动检验:  提供xml记录的部分数据,用户主动检验是否为所需文件
+
+    流程:
+    1. 解压文件,得到xml文件,项目文件
+    2. 读取xml文件,得到主要数据,与项目文件名
+    3. 读取项目文件,并检验基本数据是否与xml文件中描述一致
+    PS:用于主动检验的数据,在第2步中同步进行。要求,如果进行主动检验,必须先通过一致性检验。
+  }
   TTenderFileChecker = class
   TTenderFileChecker = class
   private
   private
-    FTempFolder: string;
     FFileName: string;
     FFileName: string;
+    FTempFolder: string;
+    FTenderFileName: string;
+    FTenderTempFolder: string;
+
+    FValid: Boolean;
+
     FPhaseCount: Integer;
     FPhaseCount: Integer;
     FAuditStatus: Integer;
     FAuditStatus: Integer;
     FProjectName: string;
     FProjectName: string;
@@ -236,11 +255,14 @@ type
     procedure LoadInfoFromXmlDocument(AXmlNode: IXMLNode);
     procedure LoadInfoFromXmlDocument(AXmlNode: IXMLNode);
     procedure LoadInfoFromXml;
     procedure LoadInfoFromXml;
     procedure LoadInfo;
     procedure LoadInfo;
+
+    function DecryptFile(const AFileName: string): Boolean;
+    function CheckFileMatchXml: Boolean;
   public
   public
-    constructor Create(AFileName: string);
-    destructor Destroy; override;
+    // 检验项目数据库数据与xml文件中主要数据是否吻合
+    function CheckFileValid(const AFileName: string): Boolean;
 
 
-    property ProjectName: string read FProjectName;
+    // xml文件中记录的信息,用于主动检验
     property PhaseCount: Integer read FPhaseCount;
     property PhaseCount: Integer read FPhaseCount;
     property AuditStatus: Integer read FAuditStatus;
     property AuditStatus: Integer read FAuditStatus;
   end;
   end;
@@ -253,19 +275,19 @@ uses
 
 
 { TSubmitProject }
 { TSubmitProject }
 
 
-procedure TSubmitProject.Execute;
+function TSubmitProject.Execute: Boolean;
 begin
 begin
   FFileType := '.rmf';
   FFileType := '.rmf';
   FNeedUpdate := True;
   FNeedUpdate := True;
   FProjectData.LockedDataForSubmit;
   FProjectData.LockedDataForSubmit;
-  inherited;
+  Result := inherited Execute;
 end;
 end;
 
 
-procedure TSubmitProject.ExportTo(AFileName: string);
+function TSubmitProject.ExportTo(AFileName: string): Boolean;
 begin
 begin
   FNeedUpdate := True;
   FNeedUpdate := True;
   FProjectData.LockedDataForSubmit;
   FProjectData.LockedDataForSubmit;
-  inherited;
+  Result := inherited ExportTo(AFileName);
 end;
 end;
 
 
 procedure TSubmitProject.OpenProject;
 procedure TSubmitProject.OpenProject;
@@ -303,24 +325,35 @@ begin
   inherited;
   inherited;
 end;
 end;
 
 
-procedure TReportBase.Execute;
+function TReportBase.Execute: Boolean;
 var
 var
   sFileName: string;
   sFileName: string;
 begin
 begin
+  Result := False;
   ExportXmlInfo;
   ExportXmlInfo;
   SaveProject;
   SaveProject;
   ZipFolder(FTempFolder, FResultFile);
   ZipFolder(FTempFolder, FResultFile);
-  sFileName := GetNewOutputFileName;
-  if SaveFile(sFileName, FFileType) then
-    CopyFileOrFolder(FResultFile, sFileName);
+  // 检验导出文件
+  if CheckFile(FResultFile) then
+  begin
+    Result := True;
+    sFileName := GetNewOutputFileName;
+    if SaveFile(sFileName, FFileType) then
+      CopyFileOrFolder(FResultFile, sFileName);
+  end;
 end;
 end;
 
 
-procedure TReportBase.ExportTo(AFileName: string);
+function TReportBase.ExportTo(AFileName: string): Boolean;
 begin
 begin
+  Result := False;
   ExportXmlInfo;
   ExportXmlInfo;
   FProjectData.SimpleSaveAs(FTempFolder + '\' + ExtractSimpleFileName(FFileName));
   FProjectData.SimpleSaveAs(FTempFolder + '\' + ExtractSimpleFileName(FFileName));
   ZipFolder(FTempFolder, FResultFile);
   ZipFolder(FTempFolder, FResultFile);
-  CopyFileOrFolder(FResultFile, AFileName);
+  if CheckFile(FResultFile) then
+  begin
+    Result := True;
+    CopyFileOrFolder(FResultFile, AFileName);
+  end;
 end;
 end;
 
 
 procedure TReportBase.ExportXmlInfo;
 procedure TReportBase.ExportXmlInfo;
@@ -402,19 +435,32 @@ begin
   vProp := AXmlNode.AddChild('TenderProperty');
   vProp := AXmlNode.AddChild('TenderProperty');
 end;
 end;
 
 
+function TReportBase.CheckFile(const AFileName: string): Boolean;
+var
+  vChecker: TTenderFileChecker;
+begin
+  Result := False;
+  vChecker := TTenderFileChecker.Create;
+  try
+    Result := vChecker.CheckFileValid(AFileName);
+  finally
+    vChecker.Free;
+  end;
+end;
+
 { TReplyProject }
 { TReplyProject }
 
 
-procedure TReplyProject.Execute;
+function TReplyProject.Execute: Boolean;
 begin
 begin
   FFileType := '.arf';
   FFileType := '.arf';
   FProjectData.LockedDataForReply;
   FProjectData.LockedDataForReply;
-  inherited;
+  Result := inherited Execute;
 end;
 end;
 
 
-procedure TReplyProject.ExportTo(AFileName: string);
+function TReplyProject.ExportTo(AFileName: string): Boolean;
 begin
 begin
   FProjectData.LockedDataForReply;
   FProjectData.LockedDataForReply;
-  inherited;
+  Result := inherited ExportTo(AFileName);
 end;
 end;
 
 
 procedure TReplyProject.OpenProject;
 procedure TReplyProject.OpenProject;
@@ -986,18 +1032,41 @@ end;
 
 
 { TTenderFileChecker }
 { TTenderFileChecker }
 
 
-constructor TTenderFileChecker.Create(AFileName: string);
+function TTenderFileChecker.CheckFileMatchXml: Boolean;
+var
+  FProjectData: TProjectData;
+begin
+  FProjectData := TProjectData.Create;
+  try
+    try
+      FProjectData.SimpleOpen(FTenderFileName);
+      Result := FProjectData.CheckDataBaseInfo(FPhaseCount, FAuditStatus);
+    except
+      Result := False;
+    end;
+  finally
+    FProjectData.Free;
+  end;
+end;
+
+function TTenderFileChecker.CheckFileValid(const AFileName: string): Boolean;
 begin
 begin
-  FFileName := AFileName;
   FTempFolder := GenerateTempFolder(GetTempFilePath);
   FTempFolder := GenerateTempFolder(GetTempFilePath);
-  UnZipFile(FFileName, FTempFolder);
-  LoadInfo;
+  FTenderTempFolder := FTempFolder + '\Tender';
+  CreateDirectoryInDeep(FTenderTempFolder);
+  try
+    Result := DecryptFile(AFileName) and CheckFileMatchXml;
+  finally
+    DeleteFileOrFolder(FTempFolder);
+  end;
 end;
 end;
 
 
-destructor TTenderFileChecker.Destroy;
+function TTenderFileChecker.DecryptFile(const AFileName: string): Boolean;
 begin
 begin
-  DeleteFileOrFolder(FTempFolder);
-  inherited;
+  Result := UnZipFile(AFileName, FTempFolder);
+  if not Result then Exit;
+  LoadInfo;
+  Result := UnZipFile(FTenderFileName, FTenderTempFolder);
 end;
 end;
 
 
 procedure TTenderFileChecker.LoadInfo;
 procedure TTenderFileChecker.LoadInfo;
@@ -1036,6 +1105,7 @@ begin
   FProjectName := AXmlNode.Attributes['ProjectName'];
   FProjectName := AXmlNode.Attributes['ProjectName'];
   FPhaseCount := AXmlNode.Attributes['PhaseCount'];
   FPhaseCount := AXmlNode.Attributes['PhaseCount'];
   FAuditStatus := AXmlNode.Attributes['AuditStatus'];
   FAuditStatus := AXmlNode.Attributes['AuditStatus'];
+  FTenderFileName := FTempFolder + '\' + AXmlNode.Attributes['FileName'];
 end;
 end;
 
 
 end.
 end.

+ 23 - 10
Units/ProjectData.pas

@@ -132,10 +132,13 @@ type
     {创建审核数据}
     {创建审核数据}
     procedure UpdateDataForReceive;
     procedure UpdateDataForReceive;
 
 
-    // 上报文件
-    procedure SubmitProject(const AFileName: string = '');
-    // 批复文件
-    procedure ReplyProject(const AFileName: string = '');
+    // 上报文件:
+    { 返回值:
+      1. True 文件检验结果正确,生成文件
+      2. False 文件检验结果错误,不生成文件}
+    function SubmitProject(const AFileName: string = ''): Boolean;
+    // 批复文件: 返回值含义同上报
+    function ReplyProject(const AFileName: string = ''): Boolean;
     // json文件:清单
     // json文件:清单
     procedure ExportJson_Bills(const AFileName: string);
     procedure ExportJson_Bills(const AFileName: string);
     procedure ExportJson_Common(const AFileName: string);
     procedure ExportJson_Common(const AFileName: string);
@@ -150,6 +153,8 @@ type
 
 
     procedure CalculateAll;
     procedure CalculateAll;
 
 
+    function CheckDataBaseInfo(APhaseCount, AAuditStatus: Integer): Boolean;
+
     procedure ImportCloudTenderFile(const AFileName: string);
     procedure ImportCloudTenderFile(const AFileName: string);
 
 
     function CheckPassword: Boolean;
     function CheckPassword: Boolean;
@@ -540,31 +545,31 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TProjectData.ReplyProject(const AFileName: string = '');
+function TProjectData.ReplyProject(const AFileName: string = ''): Boolean;
 var
 var
   Replyor: TReplyProject;
   Replyor: TReplyProject;
 begin
 begin
   Replyor := TReplyProject.Create(FProjectName, FFileName, FProjectID);
   Replyor := TReplyProject.Create(FProjectName, FFileName, FProjectID);
   try
   try
     if AFileName = '' then
     if AFileName = '' then
-      Replyor.Execute
+      Result := Replyor.Execute
     else
     else
-      Replyor.ExportTo(AFileName);
+      Result := Replyor.ExportTo(AFileName);
   finally
   finally
     Replyor.Free;
     Replyor.Free;
   end;
   end;
 end;
 end;
 
 
-procedure TProjectData.SubmitProject(const AFileName: string = '');
+function TProjectData.SubmitProject(const AFileName: string = ''): Boolean;
 var
 var
   Submitor :TSubmitProject;
   Submitor :TSubmitProject;
 begin
 begin
   Submitor := TSubmitProject.Create(FProjectName, FFileName, FProjectID);
   Submitor := TSubmitProject.Create(FProjectName, FFileName, FProjectID);
   try
   try
     if AFileName = '' then
     if AFileName = '' then
-      Submitor.Execute
+      Result := Submitor.Execute
     else
     else
-      Submitor.ExportTo(AFileName);
+      Result := Submitor.ExportTo(AFileName);
   finally
   finally
     Submitor.Free;
     Submitor.Free;
   end;
   end;
@@ -1487,4 +1492,12 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TProjectData.CheckDataBaseInfo(APhaseCount, AAuditStatus: Integer): Boolean;
+begin
+  Result := (FProjProperties.PhaseCount = APhaseCount)
+         and (FProjProperties.AuditStatus = AAuditStatus);
+  if Result and (APhaseCount > 0) and (AAuditStatus <> -1) then
+    Result := PhaseData.AuditCount = AAuditStatus;
+end;
+
 end.
 end.

+ 8 - 3
Units/UtilMethods.pas

@@ -87,7 +87,7 @@ type
 
 
   {Zip}
   {Zip}
   procedure ZipFolder(AFileFolder, AFileName: string);
   procedure ZipFolder(AFileFolder, AFileName: string);
-  procedure UnZipFile(AFileName, AFileFolder: string);
+  function UnZipFile(AFileName, AFileFolder: string): Boolean;
 
 
   {Copy By Stream}
   {Copy By Stream}
   procedure CopyFileByStream(const ASourceFile, ADestFile: string);
   procedure CopyFileByStream(const ASourceFile, ADestFile: string);
@@ -771,10 +771,11 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure UnZipFile(AFileName, AFileFolder: string);
+function UnZipFile(AFileName, AFileFolder: string): Boolean;
 var
 var
   vUnZip: TVCLZip;
   vUnZip: TVCLZip;
 begin
 begin
+  Result := True;
   vUnZip := TVCLZip.Create(nil);
   vUnZip := TVCLZip.Create(nil);
   try
   try
     vUnZip.FilesList.Clear;
     vUnZip.FilesList.Clear;
@@ -786,7 +787,11 @@ begin
     vUnZip.RelativePaths := True;
     vUnZip.RelativePaths := True;
     vUnZip.DoAll := True;
     vUnZip.DoAll := True;
     vUnZip.FilesList.Add('*.*');
     vUnZip.FilesList.Add('*.*');
-    vUnZip.UnZip;
+    try
+      vUnZip.UnZip;
+    except
+      Result := False;
+    end;
   finally
   finally
     vUnZip.Free;
     vUnZip.Free;
   end;
   end;