/// <summary> /// 실적 파일 데이터를 추가한다. (동일한 업무 영역에 추가된 실적 파일 데이터가 있다면 삭제 처리된다.) /// </summary> public bool InsertDataFileSource(DataFileSource fileSource) { fileSource.ThrowIfNull(nameof(fileSource)); string procCommandName = "up_DataFileSource_Insert"; try { var command = Connection.GetStoredProcCommand(procCommandName); Connection.AddInParameter(command, "FormID", DbType.Guid, fileSource.FormId); Connection.AddInParameter(command, "FormSectionID", DbType.Guid, fileSource.FormSectionId); Connection.AddInParameter(command, "FileSourceID", DbType.Guid, fileSource.FileSourceId); Connection.AddInParameter(command, "FileTemplateID", DbType.Guid, fileSource.FileTemplateId); Connection.AddInParameter(command, "HtmlTemplateID", DbType.Guid, fileSource.HtmlTemplateId); Connection.AddInParameter(command, "CreatorId", DbType.String, fileSource.CreatorId); Connection.AddInParameter(command, "FileName", DbType.String, fileSource.FileName); Connection.AddInParameter(command, "Extension", DbType.String, fileSource.Extension); Connection.AddInParameter(command, "Size", DbType.Int64, fileSource.Size); Connection.AddInParameter(command, "Path", DbType.String, fileSource.FileRelativePath); Connection.AddInParameter(command, "Comment", DbType.String, fileSource.Comment); Connection.AddInParameter(command, "CreatedDate", DbType.DateTimeOffset, fileSource.CreatedDate); Connection.AddInParameter(command, "SourceDate", DbType.DateTimeOffset, fileSource.SourceDate); return((int)Connection.ExecuteNonQuery(command) > 0); } catch (Exception ex) { throw new DataException($"프로시져 실행 중 예기치 못한 에러가 발생했습니다.\r\n 프로시저: \"{procCommandName}\"", ex); } }
/// <summary> /// 파일 소스를 등록한다. 같은 기간에 등록된 파일 소스가 있다면 삭제 처리 된다. /// </summary> public bool AddDataFileSource(DataFileSource fileSource) { fileSource.ThrowIfNull(nameof(fileSource)); fileSource.Validate(); using (var service = new FormTableService(CurrentUser)) { // 1. FormTable, FormTableSection 체크 var formTable = service.GetFormTable(fileSource.FormId); if (formTable == null) { throw new ObjectNotFoundException($"업로드 대상이 되는 대시보드 테이블을 찾을 수 없습니다.\r\n대시보드 ID: \"{fileSource.FormId}\""); } else if (!formTable.IsEnabled || formTable.IsDeleted) { string state = formTable.IsDeleted ? "삭제" : "비활성화"; throw new InvalidOperationException($"대상 대시보드 테이블이 {state} 된 상태이므로 파일 데이터를 업로드 할 수 없습니다.\r\n대시보드 ID: \"{fileSource.FormId}\""); } var formSection = service.GetFormTableSection(fileSource.FormId, fileSource.FormSectionId); if (formSection == null) { throw new ObjectNotFoundException($"업로드 대상이 되는 업무 영역을 찾을 수 없습니다.\r\n업무영역 ID: \"{fileSource.FormSectionId}\""); } else if (!formSection.IsEnabled || formSection.IsDeleted) { string state = formTable.IsDeleted ? "삭제" : "비활성화"; throw new InvalidOperationException($"대상 업무 영역이 {state} 된 상태이므로 파일 데이터를 업로드 할 수 없습니다.\r\n업무영역 ID: \"{fileSource.FormSectionId}\""); } fileSource.FileTemplateId = formSection.FileTemplate.FileTemplateId; fileSource.HtmlTemplateId = formTable.HtmlTemplateId; using (var repo = new DashboardRepository()) { // 3. 실제 파일 경로 체크 string filePath = fileSource.GetFileAbsolutePath(DiskPathForDataFileSource); if (!File.Exists(filePath)) { logger.Error($"업로드 된 데이터 파일 소스를 찾을 수 없습니다. 파일 경로: \"{filePath}\""); throw new FileNotFoundException($"파일을 찾을 수 없습니다. 파일: \"{fileSource.FileName}\""); } var allValues = new List <DataFileCellValue>(); ExcelFileType fileType; // 4. 파일 타입 체크 if (!Enum.TryParse <ExcelFileType>(fileSource.Extension, true, out fileType)) { throw new FileLoadException($"지원하지 않는 엑셀 파일 타입입니다. 파일: \"{fileSource.FileName}\""); } // 5. 엑셀로부터 값을 읽음 using (var parser = new ExcelParser(filePath, fileType)) { var parseOption = formSection.FileTemplate.ParseOption; foreach (var kv in parseOption.Sheets) { foreach (var sheetOption in kv.Value) { string sheetName = kv.Key; var values = parser.GetValuesFromSheet(kv.Key, sheetOption, () => { return(new DataFileCellValue(fileSource.FileSourceId, sheetName) { CreatedDate = fileSource.CreatedDate }); }).Cast <DataFileCellValue>() .ToList(); allValues.AddRange(values); } } if (!allValues.Any()) { logger.Warn($"업로드 된 데이터 파일로부터 읽어들인 엑셀 값이 없습니다. 파일: \"{fileSource.FileName}\"" + $"\r\n\r\n" + $"{fileSource}"); } } // 6. DB에 추가 repo.BeginTransaction(); try { // 6. 이미 동일한 기간에 해당되는 파일이 있는지 체크 // => 있다면 삭제 var dateRange = formTable.GetDateRangeByUploadInterval(fileSource.SourceDate); var oldFileSourceList = repo.SelectDataFileSourceListBySourceDateRange(fileSource.FormId, fileSource.FormSectionId, dateRange.BeginDate, dateRange.EndDate); if (oldFileSourceList != null) { var duplicated = oldFileSourceList .Where(o => o.FileSourceId != fileSource.FileSourceId) .ToArray(); if (duplicated.Any()) { logger.Warn($"해당 기간에 파일 소스가 2개 이상 존재합니다. 파일: {duplicated.Select(o => o.FileName).ToString()}" + $"\r\n\r\n" + $"업무 영역 ID: \"{fileSource.FormSectionId}\"" + $"\r\n" + $"기간: \"{dateRange.BeginDate.ToString("yyyy-MM-dd")}\" ~ \"{dateRange.EndDate.ToString("yyyy-MM-dd")}\""); if (duplicated.Any(o => o.IsConfirmed)) { // 관리자급 권한이 없다면 오류 처리 (관리자는 컨펌된 데이터가 있더라도 업로드 가능하도록 요청) if (CurrentUser.GroupType < UserPermissionGroupType.Administrator) { if (dateRange.BeginDate.ToString("yyyy-MM-dd").Equals(dateRange.EndDate.ToString("yyyy-MM-dd"))) { throw new InvalidOperationException($"대상 기간에 이미 최종 컨펌된 데이터가 있습니다." + $"\r\n" + $"기간: \"{dateRange.BeginDate.ToString("yyyy-MM-dd")}\""); } else { throw new InvalidOperationException($"대상 기간에 이미 최종 컨펌된 데이터가 있습니다." + $"\r\n" + $"기간: \"{dateRange.BeginDate.ToString("yyyy-MM-dd")}\" ~ \"{dateRange.EndDate.ToString("yyyy-MM-dd")}\""); } } } foreach (var o in duplicated) { if (repo.DeleteDataFileSource( formId: o.FormId, formSectionId: o.FormSectionId, fileSourceId: o.FileSourceId, deleterId: CurrentUser.UserId, deletedDate: DateTimeOffset.Now)) { logger.Warn($"새로운 데이터를 업로드 하기 위해 대상 기간에 해당되는 데이터 파일이 삭제되었습니다. 파일: \"{o.FileName}\"" + $"\r\n\r\n" + $"기간: \"{dateRange.BeginDate}\" ~ \"{dateRange.EndDate}\"" + $"\r\n\r\n" + $"{o}"); } } } } // 7 파일 데이터 추가 if (repo.InsertDataFileSource(fileSource)) { if (allValues.Any()) { repo.InsertDataFileCellValueList(formTable.FormId, formSection.FormSectionId, fileSource.FileSourceId, allValues, allValues.First().CreatedDate); } repo.CommitTransaction(); logger.Info($"새 데이터 파일을 추가하였습니다. 파일: \"{fileSource.FileName}\"" + $"\r\n\r\n" + $"{fileSource}"); return(true); } } catch (Exception ex) { logger.Error(ex, $"데이터 파일 추가 중 알 수 없는 오류가 발생하였습니다. 대시보드: \"{formSection.FormName}\", 업무영역: \"{formSection.FormSectionName}\"" + $"\r\n\r\n" + $"{formSection}"); try { repo.RollBackTransaction(); } catch (Exception rex) { logger.Fatal(ex, $"데이터 파일 추가 중 치명적인 오류가 발생하였습니다. 대시보드: \"{formSection.FormName}\", 업무영역: \"{formSection.FormSectionName}\"" + $"\r\n\r\n" + $"{formSection}"); ExceptionDispatchInfo.Capture(rex).Throw(); // not reached } ExceptionDispatchInfo.Capture(ex).Throw(); } return(false); // not reached } } }