Merge branch 'dev' into feature/sections

This commit is contained in:
Никита Фролов 2023-12-12 16:36:20 +05:00
commit f7ac9f0ccd
2 changed files with 123 additions and 72 deletions

View File

@ -1,61 +1,60 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace AsbCloudApp.Data.User namespace AsbCloudApp.Data.User;
/// <summary>
/// Контакт
/// </summary>
public class ContactDto : IId
{ {
/// <inheritdoc/>
public int Id { get; set; }
/// <summary> /// <summary>
/// Контакт /// ключ типа компании
/// </summary> /// </summary>
[Required]
[Range(1, int.MaxValue)]
public int IdCompanyType { get; set; }
public class ContactDto : IId /// <summary>
{ /// ключ скважины
/// <inheritdoc/> /// </summary>
public int Id { get; set; } [Required]
[Range(1,int.MaxValue)]
public int IdWell { get; set; }
/// <summary> /// <summary>
/// ключ типа компании /// ФИО
/// </summary> /// </summary>
[Required] [Required]
public int IdCompanyType { get; set; } [StringLength(260, MinimumLength = 0, ErrorMessage = "Допустимая длина ФИО от 1 до 260 символов")]
public string FullName { get; set; } = null!;
/// <summary> /// <summary>
/// ключ скважины /// Email
/// </summary> /// </summary>
[Required] [RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage = "Некорректный email")]
public int IdWell { get; set; } public string? Email { get; set; }
/// <summary> /// <summary>
/// ФИО /// Phone
/// </summary> /// </summary>
[Required] [RegularExpression(@"^(?:\+7|8)\s?(?:\(\d{3}\)|\d{3})\s?\d{3}-?\d{2}-?\d{2}$", ErrorMessage = "Некорректный номер телефона")]
[StringLength(260, MinimumLength = 0, ErrorMessage = "Допустимая длина ФИО от 1 до 260 символов")] public string? Phone { get; set; }
public string FullName { get; set; } = null!;
/// <summary> /// <summary>
/// Email /// Должность
/// </summary> /// </summary>
[RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage = "Некорректный email")] [Required]
public string? Email { get; set; } [StringLength(260, MinimumLength = 1, ErrorMessage = "Допустимая длина должности от 1 до 260 символов")]
public string Position { get; set; } = null!;
/// <summary> /// <summary>
/// Phone /// Компания
/// </summary> /// </summary>
[RegularExpression(@"^(?:\+7|8)\s?(?:\(\d{3}\)|\d{3})\s?\d{3}-?\d{2}-?\d{2}$", ErrorMessage = "Некорректный номер телефона")] [Required]
public string? Phone { get; set; } [StringLength(260, MinimumLength = 3, ErrorMessage = "Допустимая длина названия компании от 3 до 260 символов")]
public string Company { get; set; } = null!;
/// <summary>
/// Должность
/// </summary>
[Required]
[StringLength(260, MinimumLength = 1, ErrorMessage = "Допустимая длина должности от 1 до 260 символов")]
public string Position { get; set; } = null!;
/// <summary>
/// Компания
/// </summary>
[Required]
[StringLength(260, MinimumLength = 3, ErrorMessage = "Допустимая длина должности от 3 до 260 символов")]
public string Company { get; set; } = null!;
}
} }

View File

@ -16,6 +16,8 @@ using AsbCloudApp.Data.WellOperationImport;
using AsbCloudApp.Services.WellOperationImport; using AsbCloudApp.Services.WellOperationImport;
using AsbCloudApp.Data.WellOperationImport.Options; using AsbCloudApp.Data.WellOperationImport.Options;
using AsbCloudApp.Exceptions; using AsbCloudApp.Exceptions;
using AsbCloudDb.Model;
using AsbCloudInfrastructure;
namespace AsbCloudWebApi.Controllers namespace AsbCloudWebApi.Controllers
{ {
@ -266,7 +268,7 @@ namespace AsbCloudWebApi.Controllers
if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken))
return Forbid(); return Forbid();
if (deleteBeforeInsert && wellOperations.Any()) if (deleteBeforeInsert)
{ {
var existingOperations = await operationRepository.GetAsync(new WellOperationRequest var existingOperations = await operationRepository.GetAsync(new WellOperationRequest
{ {
@ -344,46 +346,85 @@ namespace AsbCloudWebApi.Controllers
return Ok(result); return Ok(result);
} }
/// <summary> /// <summary>
/// Импорт операций из excel (xlsx) файла. Стандартный заполненный шаблон /// Импорт фактических операций из excel (xlsx) файла. Стандартный заполненный шаблон
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="files">Коллекция из одного файла xlsx</param>
/// <param name="deleteBeforeInsert">Удалить операции перед сохранением</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("import/fact/default/{deleteBeforeInsert:bool}")]
[ProducesResponseType(typeof(IEnumerable<WellOperationDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
[Permission]
public Task<IActionResult> ImportFactDefaultExcelFileAsync(int idWell,
[FromForm] IFormFileCollection files,
bool deleteBeforeInsert,
CancellationToken cancellationToken)
{
var options = new WellOperationImportDefaultOptionsDto
{
IdType = WellOperation.IdOperationTypeFact
};
return ImportExcelFileAsync(idWell, files, options,
(stream, _) => wellOperationDefaultExcelParser.Parse(stream, options),
deleteBeforeInsert,
cancellationToken);
}
/// <summary>
/// Импорт плановых операций из excel (xlsx) файла. Стандартный заполненный шаблон
/// </summary> /// </summary>
/// <param name="idWell">id скважины</param> /// <param name="idWell">id скважины</param>
/// <param name="options">Параметры для парсинга файла</param>
/// <param name="files">Коллекция из одного файла xlsx</param> /// <param name="files">Коллекция из одного файла xlsx</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("import/default")] [HttpPost("import/plan/default")]
[ProducesResponseType(typeof(IEnumerable<WellOperationDto>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(IEnumerable<WellOperationDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[Permission] [Permission]
public Task<IActionResult> ImportDefaultExcelFileAsync(int idWell, public Task<IActionResult> ImportPlanDefaultExcelFileAsync(int idWell,
[FromQuery] WellOperationImportDefaultOptionsDto options,
[FromForm] IFormFileCollection files, [FromForm] IFormFileCollection files,
CancellationToken cancellationToken) => ImportExcelFileAsync(idWell, files, options, CancellationToken cancellationToken)
(stream, _) => wellOperationDefaultExcelParser.Parse(stream, options), {
cancellationToken); var options = new WellOperationImportDefaultOptionsDto
{
IdType = WellOperation.IdOperationTypePlan
};
return ImportExcelFileAsync(idWell, files, options,
(stream, _) => wellOperationDefaultExcelParser.Parse(stream, options),
null,
cancellationToken);
}
/// <summary> /// <summary>
/// Импорт операций из excel (xlsx) файла. ГПНХ (Хантос) /// Импорт операций из excel (xlsx) файла. ГПНХ (Хантос)
/// </summary> /// </summary>
/// <param name="idWell">id скважины</param> /// <param name="idWell">id скважины</param>
/// <param name="options">Параметры для парсинга файла</param>
/// <param name="files">Коллекция из одного файла xlsx</param> /// <param name="files">Коллекция из одного файла xlsx</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("import/gazpromKhantos")] [HttpPost("import/plan/gazpromKhantos")]
[ProducesResponseType(typeof(IEnumerable<WellOperationDto>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(IEnumerable<WellOperationDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[Permission] [Permission]
public Task<IActionResult> ImportGazpromKhantosExcelFileAsync(int idWell, public Task<IActionResult> ImportPlanGazpromKhantosExcelFileAsync(int idWell,
[FromQuery] WellOperationImportGazpromKhantosOptionsDto options,
[FromForm] IFormFileCollection files, [FromForm] IFormFileCollection files,
CancellationToken cancellationToken) => ImportExcelFileAsync(idWell, files, options, CancellationToken cancellationToken)
(stream, _) => wellOperationGazpromKhantosExcelParser.Parse(stream, options), {
cancellationToken); var options = new WellOperationImportGazpromKhantosOptionsDto
{
IdType = WellOperation.IdOperationTypePlan
};
return ImportExcelFileAsync(idWell, files, options,
(stream, _) => wellOperationGazpromKhantosExcelParser.Parse(stream, options),
null,
cancellationToken);
}
/// <summary> /// <summary>
/// Создает excel файл с операциями по скважине /// Создает excel файл с операциями по скважине
@ -451,9 +492,11 @@ namespace AsbCloudWebApi.Controllers
return File(stream, "application/octet-stream", fileName); return File(stream, "application/octet-stream", fileName);
} }
//TODO: deleteBeforeInsert тоже быстрый костыль
private async Task<IActionResult> ImportExcelFileAsync<TOptions>(int idWell, [FromForm] IFormFileCollection files, private async Task<IActionResult> ImportExcelFileAsync<TOptions>(int idWell, [FromForm] IFormFileCollection files,
TOptions options, TOptions options,
Func<Stream, TOptions, SheetDto> parseMethod, Func<Stream, TOptions, SheetDto> parseMethod,
bool? deleteBeforeInsert,
CancellationToken cancellationToken) CancellationToken cancellationToken)
where TOptions : IWellOperationImportOptions where TOptions : IWellOperationImportOptions
{ {
@ -488,13 +531,22 @@ namespace AsbCloudWebApi.Controllers
var wellOperations = wellOperationImportService.Import(idWell, idUser.Value, options.IdType, sheet) var wellOperations = wellOperationImportService.Import(idWell, idUser.Value, options.IdType, sheet)
.OrderBy(w => w.DateStart); .OrderBy(w => w.DateStart);
var dateStart = wellOperations.Min(w => w.DateStart); var dateStart = wellOperations.MinOrDefault(w => w.DateStart);
foreach (var wellOperation in wellOperations) foreach (var wellOperation in wellOperations)
wellOperation.Day = (wellOperation.DateStart - dateStart).TotalDays; {
if (dateStart.HasValue)
wellOperation.Day = (wellOperation.DateStart - dateStart.Value).TotalDays;
}
if (!wellOperations.Any()) //TODO: очень быстрый костыль
return NoContent(); if (deleteBeforeInsert is not null && options.IdType == WellOperation.IdOperationTypeFact)
{
return await InsertRangeAsync(idWell, options.IdType,
deleteBeforeInsert.Value,
wellOperations,
cancellationToken);
}
return Ok(wellOperations); return Ok(wellOperations);
} }