Add DrillingProgramController

This commit is contained in:
Фролов 2021-08-29 17:25:16 +05:00
parent 002da70471
commit 14cf99a1dd
14 changed files with 343 additions and 159 deletions

View File

@ -5,8 +5,10 @@ namespace AsbCloudApp.Data
public class FileInfoDto
{
public int Id { get; set; }
public string Name { get; set; }
public int IdWell { get; set; }
public int IdCategory { get; set; }
public int IdAuthor { get; set; }
public string Name { get; set; }
public DateTime UploadDate { get; set; }
public string AuthorName { get; set; }
public int CompanyId { get; set; }

View File

@ -0,0 +1,11 @@
using AsbCloudApp.Data;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services
{
public interface IDrillingProgramService
{
Task<FileInfoDto> GetAsync(int idWell, CancellationToken token = default);
}
}

View File

@ -10,20 +10,20 @@ namespace AsbCloudApp.Services
public interface IFileService
{
string RootPath { get; }
IDictionary<string, int> SaveFileInfos(int idWell, int idUser,
IEnumerable<FileInfoDto> filesInfo);
Task SaveFile(int idWell, int idCategory, int fileId,
string fileExtension, Stream fileStream);
Task<FileInfoDto> SaveAsync(int idWell, int idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token = default);
Task<PaginationContainer<FileInfoDto>> GetFilesInfoAsync(int idWell,
Task<PaginationContainer<FileInfoDto>> GetInfosAsync(int idWell,
int idCategory, IEnumerable<int> companies, DateTime begin, DateTime end,
int skip, int take, CancellationToken token = default);
Task<FileInfoDto> GetFileInfoAsync(int fileId,
Task<FileInfoDto> GetInfoAsync(int fileId,
CancellationToken token);
Task<int> DeleteFileAsync(int idFile,
Task<int> MarkAsDeletedAsync(int idFile,
CancellationToken token = default);
Task<IEnumerable<FileInfoDto>> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token = default);
Task<int> DeletedAsync(int id, CancellationToken token);
string GetFileName(FileInfoDto fileInfo);
}
}

View File

@ -13,5 +13,6 @@ namespace AsbCloudApp.Services
Task<IEnumerable<WellOperationDto>> GetOperationsAsync(int idWell, CancellationToken token);
Task<string> GetWellCaptionByIdAsync(int idWell, CancellationToken token);
Task<IEnumerable<CompanyDto>> GetCompaniesAsync(int idWell, CancellationToken token);
Task<WellDto> GetAsync(int idWell, CancellationToken token);
}
}

View File

@ -285,7 +285,8 @@ namespace AsbCloudDb.Model
new FileCategory {Id = 9, Name = "Последний замер бурового раствора ФАКТ", ShortName = "fluidFactLastData"},
new FileCategory {Id = 10, Name = "Последние данные Шламограммы", ShortName = "mudLastData"},
new FileCategory {Id = 11, Name = "Последние данные ННБ", ShortName = "nnbLastData"},
new FileCategory {Id = 12, Name = "Рапорт", ShortName = "report"}
new FileCategory {Id = 12, Name = "Рапорт", ShortName = "report"},
new FileCategory {Id = 13, Name = "Программа бурения", ShortName = "ПБ"},
});
});

View File

@ -12,6 +12,7 @@
<PackageReference Include="itext7" Version="7.1.15" />
<PackageReference Include="Mapster" Version="7.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="NPOI" Version="2.5.4" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.10.0" />
</ItemGroup>

View File

@ -39,6 +39,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<IWellOperationService, WellOperationService>();
services.AddTransient<IWellOperationsStatService, WellOperationsStatService>();
services.AddTransient<IMeasureService, MeasureService>();
services.AddTransient<IDrillingProgramService, DrillingProgramService>();
return services;
}

View File

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Microsoft.EntityFrameworkCore;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
namespace AsbCloudInfrastructure.Services
{
public class DrillingProgramService : IDrillingProgramService
{
private readonly IFileService fileService;
private readonly WellService wellService;
private const int idFileCategoryPlan = 13;
public DrillingProgramService(IFileService fileService, WellService wellService)
{
this.fileService = fileService;
this.wellService = wellService;
}
public async Task<FileInfoDto> GetAsync(int idWell, CancellationToken token = default)
{
var filesInfos = await fileService.GetInfosByCategoryAsync(idWell, idFileCategoryPlan, token)
.ConfigureAwait(false);
var well = await wellService.GetAsync(idWell, token)
.ConfigureAwait(false);
var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.xlsx";
var matchFile = filesInfos.FirstOrDefault(f=>f.Name == resultFileName);
if (matchFile is not null) {
if (filesInfos.All(f => f.UploadDate <= matchFile.UploadDate))
return matchFile;
else
await fileService.DeletedAsync(matchFile.Id, token);
}
var fileNames = filesInfos
.Where(f => f.Name != resultFileName)
.Select(f => fileService.GetFileName(f));
var stream = new MemoryStream(1024 * 1024);
UniteExcelFiles(fileNames, stream);
stream.Seek(0, SeekOrigin.Begin);
return await fileService.SaveAsync(idWell, 0, idFileCategoryPlan, resultFileName, stream, token)
.ConfigureAwait(false);
}
private static void UniteExcelFiles(IEnumerable<string> excelFilesNames, Stream stream)
{
IWorkbook product = new XSSFWorkbook();
foreach (var excelFileName in excelFilesNames)
{
IWorkbook book = new XSSFWorkbook(new FileStream(excelFileName, FileMode.Open));
for (int i = 0; i < book.NumberOfSheets; i++)
{
ISheet sheet = book.GetSheetAt(i);
try
{
sheet.CopyTo(product, sheet.SheetName, true, true);
}
catch
{
//what can't be done - can't be done. ignore it.
}
}
}
product.Write(stream);
}
}
}

View File

@ -23,35 +23,25 @@ namespace AsbCloudInfrastructure.Services
this.db = db;
}
public IDictionary<string, int> SaveFileInfos(int idWell, int idUser,
IEnumerable<FileInfoDto> filesInfo)
public async Task<FileInfoDto> SaveAsync(int idWell, int idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token = default)
{
var fileIdsToNames = new Dictionary<string, int>();
foreach (var fileInfo in filesInfo)
//save info to db
var fileInfo = new AsbCloudDb.Model.FileInfo()
{
var file = new AsbCloudDb.Model.FileInfo()
{
Name = fileInfo.Name,
IdWell = idWell,
IdCategory = fileInfo.IdCategory,
UploadDate = fileInfo.UploadDate,
IdAuthor = idUser
IdAuthor = idUser,
IdCategory = idCategory,
Name = Path.GetFileName(fileFullName),
UploadDate = DateTime.Now,
IsDeleted = false,
};
db.Files.Add(file);
var entry = db.Files.Add(fileInfo);
db.SaveChanges();
fileIdsToNames.Add(file.Name, file.Id);
}
return fileIdsToNames;
}
public async Task SaveFile(int idWell, int idCategory, int fileId,
string fileExtension, Stream fileStream)
{
var fileId = entry.Entity.Id;
//save stream to disk
var relativePath = Path.Combine(RootPath, $"{idWell}",
$"{idCategory}", $"{fileId}" + $"{fileExtension}");
$"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}");
Directory.CreateDirectory(Path.GetDirectoryName(relativePath));
@ -59,9 +49,30 @@ namespace AsbCloudInfrastructure.Services
{
await fileStream.CopyToAsync(newfileStream);
}
var dto = entry.Entity.Adapt<FileInfoDto>();
return dto;
}
public async Task<PaginationContainer<FileInfoDto>> GetFilesInfoAsync(int idWell,
public async Task<IEnumerable<FileInfoDto>> GetInfosByCategoryAsync(int idWell,
int idCategory, CancellationToken token = default)
{
var entities = await db.Files
.Include(f => f.Author)
.Where(e => e.IdWell == idWell && e.IdCategory == idCategory)
.AsNoTracking()
.ToListAsync(token)
.ConfigureAwait(false);
var dtos = entities.Adapt<FileInfoDto, AsbCloudDb.Model.FileInfo>((d,s) => {
d.AuthorName = s.Author?.Name;
d.CompanyId = s.Author?.IdCompany ?? 0;
});
return dtos;
}
public async Task<PaginationContainer<FileInfoDto>> GetInfosAsync(int idWell,
int idCategory, IEnumerable<int> companies = default, DateTime begin = default,
DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default)
{
@ -115,7 +126,7 @@ namespace AsbCloudInfrastructure.Services
return result;
}
public async Task<FileInfoDto> GetFileInfoAsync(int fileId,
public async Task<FileInfoDto> GetInfoAsync(int fileId,
CancellationToken token = default)
{
var entity = await db.Files
@ -132,17 +143,42 @@ namespace AsbCloudInfrastructure.Services
return dto;
}
public async Task<int> DeleteFileAsync(int idFile,
public async Task<int> MarkAsDeletedAsync(int idFile,
CancellationToken token = default)
{
var fileInfo = db.Files.FirstOrDefault(f => f.Id == idFile);
var fileInfo = await db.Files.FirstOrDefaultAsync(f => f.Id == idFile, token).ConfigureAwait(false);
if (fileInfo is null)
return 0;
fileInfo.IsDeleted = true;
return await db.SaveChangesAsync(token);
return await db.SaveChangesAsync(token).ConfigureAwait(false);
}
public async Task<int> DeletedAsync(int idFile, CancellationToken token)
{
var fileInfo = await db.Files
.FirstOrDefaultAsync(f => f.Id == idFile, token)
.ConfigureAwait(false);
if (fileInfo is null)
return 0;
var fileName = GetFileName(fileInfo.Adapt<FileInfoDto>());
if (File.Exists(fileName))
File.Delete(fileName);
db.Files.Remove(fileInfo);
return await db.SaveChangesAsync(token).ConfigureAwait(false);
}
public string GetFileName(FileInfoDto fileInfo)
{
var fileName = Path.Combine(fileInfo.Id.ToString(), Path.GetExtension(fileInfo.Name));
fileName = Path.Combine(RootPath, fileInfo.IdWell.ToString(), fileInfo.IdCategory.ToString(), fileName);
fileName = Path.GetFullPath(fileName);
return fileName;
}
}
}

View File

@ -77,6 +77,19 @@ namespace AsbCloudInfrastructure.Services
return wellDto;
}
public async Task<WellDto> GetAsync(int idWell, CancellationToken token)
{
var entity = await db.Wells
.Include(w=>w.Cluster)
.ThenInclude(c=>c.Deposit)
.FirstOrDefaultAsync(w => w.Id == idWell, token)
.ConfigureAwait(false);
var dto = entity.Adapt<WellDto>();
dto.Cluster = entity.Cluster?.Caption;
dto.Deposit = entity.Cluster?.Deposit?.Caption;
return dto;
}
public async Task<string> GetWellCaptionByIdAsync(int idWell, CancellationToken token)
{
var entity = await cacheWells.FirstOrDefaultAsync(w => w.Id == idWell, token).ConfigureAwait(false);

View File

@ -0,0 +1,34 @@
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudWebApi.Controllers
{
[Route("api/well/{idWell}/files")]
[ApiController]
[Authorize]
public class DrillingProgramController : ControllerBase
{
private readonly IDrillingProgramService drillingProgramService;
private readonly IFileService fileService;
public DrillingProgramController(IDrillingProgramService drillingProgramService, IFileService fileService)
{
this.drillingProgramService = drillingProgramService;
this.fileService = fileService;
}
[HttpGet]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetAsync(int idWell, CancellationToken token = default)
{
var fileInfo = await drillingProgramService.GetAsync(idWell, token)
.ConfigureAwait(false);
var relativePath = fileService.GetFileName(fileInfo);
return PhysicalFile(Path.GetFullPath(relativePath), "application/octet-stream", fileInfo.Name);
}
}
}

View File

@ -56,20 +56,11 @@ namespace AsbCloudWebApi.Controllers
UploadDate = DateTime.Now
});
var fileNamesAndIds = fileService.SaveFileInfos(idWell, (int)idUser,
fileInfoCollection);
foreach (var file in files)
{
var fileExtension = Path.GetExtension(file.FileName);
var fileId = fileNamesAndIds[file.FileName];
var fileStream = file.OpenReadStream();
await fileService.SaveFile(idWell, idCategory, fileId,
fileExtension, fileStream);
await fileService.SaveAsync(idWell, idUser??0, idCategory, file.FileName,
fileStream);
}
return Ok();
@ -100,7 +91,7 @@ namespace AsbCloudWebApi.Controllers
idWell, token).ConfigureAwait(false))
return Forbid();
var filesInfo = await fileService.GetFilesInfoAsync(idWell, idCategory,
var filesInfo = await fileService.GetInfosAsync(idWell, idCategory,
companies, begin, end, skip, take, token).ConfigureAwait(false);
if (filesInfo is null || !filesInfo.Items.Any())
@ -133,14 +124,13 @@ namespace AsbCloudWebApi.Controllers
idWell, token).ConfigureAwait(false))
return Forbid();
var fileInfo = await fileService.GetFileInfoAsync(fileId, token);
var fileInfo = await fileService.GetInfoAsync(fileId, token);
if (fileInfo is null)
throw new FileNotFoundException();
// TODO: словарь content typoв
var relativePath = Path.Combine(fileService.RootPath, $"{idWell}", $"{fileInfo.IdCategory}",
$"{fileInfo.Id}" + Path.GetExtension($"{fileInfo.Name}"));
var relativePath = fileService.GetFileName(fileInfo);
return PhysicalFile(Path.GetFullPath(relativePath), "application/octet-stream", fileInfo.Name);
}
catch (FileNotFoundException ex)
@ -167,7 +157,7 @@ namespace AsbCloudWebApi.Controllers
idWell, token).ConfigureAwait(false))
return Forbid();
var result = await fileService.DeleteFileAsync(idFile, token);
var result = await fileService.MarkAsDeletedAsync(idFile, token);
return Ok(result);
}

View File

@ -7,6 +7,7 @@
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
<PackageReference Include="DocumentFormat.OpenXml" Version="2.13.1" />
<PackageReference Include="Mapster" Version="7.2.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="5.0.5" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />

View File

@ -2,6 +2,9 @@
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services;
using AsbCloudInfrastructure.Services.Cache;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
//using AsbSaubReport;
//using AutoMapper;
using Microsoft.EntityFrameworkCore;
@ -15,29 +18,38 @@ namespace ConsoleApp1
static void Main(/*string[] args*/)
{
var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
.UseNpgsql("Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True")
.Options;
var context = new AsbCloudDbContext(options);
//var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
// .UseNpgsql("Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True")
// .Options;
//var context = new AsbCloudDbContext(options);
var mservice = new MeasureService(context, new CacheDb());
var r = mservice.GetAllLastAsync(1, default).Result;
var fileNames = new string[] { @"d:\temp\1\book1.xlsx", @"d:\temp\1\book2.xlsx" };
//var idWell = 1;
//var dataSource = new ReportDataSourcePgCloud(context, idWell);
//var generator = new PdfGenerator(dataSource)
//{
// ReportDirectory = $"{idWell}",
// Begin = DateTime.Now.AddYears(-30),
// End = DateTime.Now.AddYears(30),
// Step = TimeSpan.FromDays(1),
// WithCharts = true,
// WithEvents = true
//};
using var spreadsheetDocument = SpreadsheetDocument.Create(@"d:\temp\1\b.xlsx", SpreadsheetDocumentType.Workbook);
// Add a WorkbookPart and Workbook objects.
WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
//generator.OnProgress += Generator_OnProgress;
//var s = generator.GetPagesCount();
//var fileName = generator.Make();
// Add a WorksheetPart to the WorkbookPart.
WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet(new SheetData());
// Add Sheets to the Workbook.
Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.
AppendChild<Sheets>(new Sheets());
// Append a new worksheet and associate it with the workbook.
Sheet sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.
GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "mySheetNameISHere!"
};
sheets.Append(sheet);
spreadsheetDocument.Save();
spreadsheetDocument.Close();
Console.WriteLine("Done. Press any key to quit.");
Console.ReadKey();