forked from ddrilling/AsbCloudServer
DrillingProgramService существенно переработан.
This commit is contained in:
parent
4c68045398
commit
e4e906c8d7
@ -5,8 +5,14 @@ namespace AsbCloudApp.Data
|
||||
public class DrillingProgramPartDto
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public int IdFileCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 0 - NoFile
|
||||
/// 1 - approving
|
||||
/// 2 - completely approved
|
||||
/// </summary>
|
||||
public int IdState { get; set; }
|
||||
public IEnumerable<UserDto> Publishers { get; set; }
|
||||
public IEnumerable<UserDto> Approvers { get; set; }
|
||||
public bool PermissionToApprove { get; set; }
|
||||
|
15
AsbCloudApp/Data/FileCategoryDto.cs
Normal file
15
AsbCloudApp/Data/FileCategoryDto.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Data
|
||||
{
|
||||
public class FileCategoryDto : IId
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string ShortName { get; set; }
|
||||
}
|
||||
}
|
@ -6,6 +6,10 @@ namespace AsbCloudApp.Data
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int IdFile { get; set; }
|
||||
/// <summary>
|
||||
/// 0 - отклонен
|
||||
/// 1 - согласован
|
||||
/// </summary>
|
||||
public int IdMarkType { get; set; }
|
||||
/// <summary>
|
||||
/// äàòà/âðåìÿ äîáàâëåíèÿ.
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
namespace AsbCloudApp.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Argument validation fail Exception
|
||||
/// </summary>
|
||||
public class ArgumentInvalidException: Exception
|
||||
{
|
||||
public string ParamName { get; }
|
||||
@ -11,5 +14,15 @@ namespace AsbCloudApp.Exceptions
|
||||
{
|
||||
ParamName = paramName;
|
||||
}
|
||||
|
||||
public object ToValaidationErrorObject()
|
||||
=> MakeValidationError(ParamName, Message);
|
||||
|
||||
public static object MakeValidationError(string paramName, params string[] errors)
|
||||
=> new
|
||||
{
|
||||
name = paramName,
|
||||
errors = errors,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
17
AsbCloudApp/Exceptions/ForbidException.cs
Normal file
17
AsbCloudApp/Exceptions/ForbidException.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace AsbCloudApp.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Access denied exception
|
||||
/// </summary>
|
||||
public class ForbidException: Exception
|
||||
{
|
||||
public ForbidException()
|
||||
:base(){}
|
||||
|
||||
public ForbidException(string message)
|
||||
:base(message){}
|
||||
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
using AsbCloudApp.Data;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -6,9 +8,15 @@ namespace AsbCloudApp.Services
|
||||
{
|
||||
public interface IDrillingProgramService
|
||||
{
|
||||
Task<IEnumerable<FileCategoryDto>> GetCategoriesAsync(CancellationToken token = default);
|
||||
Task<DrillingProgramStateDto> GetStateAsync(int idWell, int fileChangerId,
|
||||
CancellationToken token = default);
|
||||
Task<int> CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token);
|
||||
Task<int> MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token);
|
||||
Task<int> AddOrReplaceFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token);
|
||||
Task<int> MarkAsDeletedFileMarkAsync(int idFileMark, CancellationToken token);
|
||||
Task<int> AddPartAsync(int idWell, int idFileCategory, CancellationToken token = default);
|
||||
Task<int> RemovePartAsync(int idWell, int idFileCategory, CancellationToken token = default);
|
||||
Task<int> AddUserAsync(int idUser, int idPart, int idUserRole, CancellationToken token = default);
|
||||
Task<int> RemoveUserAsync(int idUser, int idPart, int idUserRole, CancellationToken token = default);
|
||||
Task<int> AddFile(int idPart, int idUser, string fileFullName, Stream fileStream, CancellationToken token = default);
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ namespace AsbCloudApp.Services
|
||||
CancellationToken token = default);
|
||||
Task<IEnumerable<FileInfoDto>> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token = default);
|
||||
Task<int> DeleteAsync(int id, CancellationToken token);
|
||||
Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token);
|
||||
string GetUrl(FileInfoDto fileInfo);
|
||||
string GetUrl(int idFile);
|
||||
string GetUrl(int idWell, int idCategory, int idFile, string dotExtention);
|
||||
@ -35,5 +36,6 @@ namespace AsbCloudApp.Services
|
||||
Task<int> MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token);
|
||||
Task<FileInfoDto> MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFileFullName, CancellationToken token = default);
|
||||
Task<FileInfoDto> GetByMarkId(int idMark, CancellationToken token);
|
||||
Task<int> MarkFileMarkAsDeletedAsync(IEnumerable<int> idsMarks, CancellationToken token);
|
||||
}
|
||||
}
|
||||
|
4980
AsbCloudDb/Migrations/20220209093528_Add_DrillingProgram_parts.Designer.cs
generated
Normal file
4980
AsbCloudDb/Migrations/20220209093528_Add_DrillingProgram_parts.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,90 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Add_DrillingProgram_parts : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "t_drilling_program_part",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
id_well = table.Column<int>(type: "integer", nullable: false),
|
||||
id_file_category = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_t_drilling_program_part", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_drilling_program_part_t_file_category_id_file_category",
|
||||
column: x => x.id_file_category,
|
||||
principalTable: "t_file_category",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_drilling_program_part_t_well_id_well",
|
||||
column: x => x.id_well,
|
||||
principalTable: "t_well",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
},
|
||||
comment: "части программ бурения");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "t_relation_user_drilling_program_part",
|
||||
columns: table => new
|
||||
{
|
||||
id_user = table.Column<int>(type: "integer", nullable: false),
|
||||
id_drilling_program_part = table.Column<int>(type: "integer", nullable: false),
|
||||
id_role = table.Column<int>(type: "integer", nullable: false, comment: "1 - publisher, 2 - approver")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("t_relation_user_drilling_program_part_pk", x => new { x.id_user, x.id_drilling_program_part });
|
||||
table.ForeignKey(
|
||||
name: "FK_t_relation_user_drilling_program_part_t_drilling_program_pa~",
|
||||
column: x => x.id_drilling_program_part,
|
||||
principalTable: "t_drilling_program_part",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_relation_user_drilling_program_part_t_user_id_user",
|
||||
column: x => x.id_user,
|
||||
principalTable: "t_user",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
},
|
||||
comment: "Отношение пользователей и частей ПБ");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_drilling_program_part_id_file_category",
|
||||
table: "t_drilling_program_part",
|
||||
column: "id_file_category");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_drilling_program_part_id_well",
|
||||
table: "t_drilling_program_part",
|
||||
column: "id_well");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_relation_user_drilling_program_part_id_drilling_program_p~",
|
||||
table: "t_relation_user_drilling_program_part",
|
||||
column: "id_drilling_program_part");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "t_relation_user_drilling_program_part");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "t_drilling_program_part");
|
||||
}
|
||||
}
|
||||
}
|
4981
AsbCloudDb/Migrations/20220209102754_DrillingProgram_parts_Add_unique_constrain.Designer.cs
generated
Normal file
4981
AsbCloudDb/Migrations/20220209102754_DrillingProgram_parts_Add_unique_constrain.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class DrillingProgram_parts_Add_unique_constrain : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_t_drilling_program_part_id_well",
|
||||
table: "t_drilling_program_part");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_drilling_program_part_id_well_id_file_category",
|
||||
table: "t_drilling_program_part",
|
||||
columns: new[] { "id_well", "id_file_category" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_t_drilling_program_part_id_well_id_file_category",
|
||||
table: "t_drilling_program_part");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_drilling_program_part_id_well",
|
||||
table: "t_drilling_program_part",
|
||||
column: "id_well");
|
||||
}
|
||||
}
|
||||
}
|
@ -266,6 +266,35 @@ namespace AsbCloudDb.Migrations
|
||||
b.HasComment("Параметры коридоров бурения (диапазоны параметров бурения)");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("IdFileCategory")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_file_category");
|
||||
|
||||
b.Property<int>("IdWell")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_well");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("IdFileCategory");
|
||||
|
||||
b.HasIndex("IdWell", "IdFileCategory")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("t_drilling_program_part");
|
||||
|
||||
b.HasComment("части программ бурения");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.DrillParams", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@ -1354,6 +1383,31 @@ namespace AsbCloudDb.Migrations
|
||||
b.HasComment("отношение скважин и компаний");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.RelationUserDrillingProgramPart", b =>
|
||||
{
|
||||
b.Property<int>("IdUser")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_user");
|
||||
|
||||
b.Property<int>("IdDrillingProgramPart")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_drilling_program_part");
|
||||
|
||||
b.Property<int>("IdDrillingProgramPartRole")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_role")
|
||||
.HasComment("1 - publisher, 2 - approver");
|
||||
|
||||
b.HasKey("IdUser", "IdDrillingProgramPart")
|
||||
.HasName("t_relation_user_drilling_program_part_pk");
|
||||
|
||||
b.HasIndex("IdDrillingProgramPart");
|
||||
|
||||
b.ToTable("t_relation_user_drilling_program_part");
|
||||
|
||||
b.HasComment("Отношение пользователей и частей ПБ");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.RelationUserRolePermission", b =>
|
||||
{
|
||||
b.Property<int>("IdUserRole")
|
||||
@ -4399,6 +4453,25 @@ namespace AsbCloudDb.Migrations
|
||||
b.Navigation("Well");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.FileCategory", "FileCategory")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdFileCategory")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("AsbCloudDb.Model.Well", "Well")
|
||||
.WithMany("DrillingProgramParts")
|
||||
.HasForeignKey("IdWell")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("FileCategory");
|
||||
|
||||
b.Navigation("Well");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.DrillParams", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.Well", "Well")
|
||||
@ -4505,6 +4578,25 @@ namespace AsbCloudDb.Migrations
|
||||
b.Navigation("Well");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.RelationUserDrillingProgramPart", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.DrillingProgramPart", "DrillingProgramPart")
|
||||
.WithMany("RelatedUsers")
|
||||
.HasForeignKey("IdDrillingProgramPart")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("AsbCloudDb.Model.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdUser")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("DrillingProgramPart");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.RelationUserRolePermission", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.Permission", "Permission")
|
||||
@ -4795,6 +4887,11 @@ namespace AsbCloudDb.Migrations
|
||||
b.Navigation("Clusters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b =>
|
||||
{
|
||||
b.Navigation("RelatedUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.FileInfo", b =>
|
||||
{
|
||||
b.Navigation("FileMarks");
|
||||
@ -4847,6 +4944,8 @@ namespace AsbCloudDb.Migrations
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.Well", b =>
|
||||
{
|
||||
b.Navigation("DrillingProgramParts");
|
||||
|
||||
b.Navigation("RelationCompaniesWells");
|
||||
|
||||
b.Navigation("WellCompositeSrcs");
|
||||
|
@ -238,7 +238,12 @@ namespace AsbCloudDb.Model
|
||||
{
|
||||
entity.HasIndex(d => d.IdWellOperationCategory);
|
||||
});
|
||||
|
||||
|
||||
modelBuilder.Entity<DrillingProgramPart>(entity => {
|
||||
entity.HasIndex(x => new { x.IdWell, x.IdFileCategory})
|
||||
.IsUnique();
|
||||
});
|
||||
|
||||
modelBuilder.Entity<FileMark>(entity =>
|
||||
{
|
||||
entity.HasOne(d => d.User)
|
||||
|
@ -13,10 +13,15 @@ namespace AsbCloudDb.Model
|
||||
[Column("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("id_well")]
|
||||
public int IdWell { get; set; }
|
||||
|
||||
[Column("id_file_category")]
|
||||
[Required]
|
||||
public int IdFileCategory { get; set; }
|
||||
|
||||
[ForeignKey(nameof(IdWell))]
|
||||
public Well Well { get; set; }
|
||||
|
||||
[ForeignKey(nameof(IdFileCategory))]
|
||||
public FileCategory FileCategory { get; set; }
|
||||
|
||||
|
@ -16,7 +16,7 @@ namespace AsbCloudDb.Model
|
||||
[Column("id_file"), Comment("id файла")]
|
||||
public int IdFile { get; set; }
|
||||
|
||||
[Column("id_mark_type"), Comment("0 - Согласован")]
|
||||
[Column("id_mark_type"), Comment("0 - отклонен, 1 - согласован")]
|
||||
public int IdMarkType { get; set; }
|
||||
|
||||
[Column("date_created", TypeName = "timestamp with time zone"), Comment("Дата совершенного действия")]
|
||||
|
@ -39,6 +39,8 @@ namespace AsbCloudDb.Model
|
||||
DbSet<RelationUserRolePermission> RelationUserRolePermissions { get; set; }
|
||||
|
||||
DatabaseFacade Database { get; }
|
||||
DbSet<DrillingProgramPart> DrillingProgramParts { get; set; }
|
||||
DbSet<RelationUserDrillingProgramPart> RelationDrillingProgramPartUsers { get; set; }
|
||||
|
||||
int SaveChanges();
|
||||
int SaveChanges(bool acceptAllChangesOnSuccess);
|
||||
|
@ -13,13 +13,13 @@ namespace AsbCloudDb.Model
|
||||
public int IdDrillingProgramPart { get; set; }
|
||||
|
||||
[Column("id_role"), Comment("1 - publisher, 2 - approver")]
|
||||
public int IdDrillingProgramPartRole { get; set; }
|
||||
public int IdUserRole { get; set; }
|
||||
|
||||
[ForeignKey(nameof(IdDrillingProgramPart))]
|
||||
[InverseProperty(nameof(Model.DrillingProgramPart.RelatedUsers))]
|
||||
public virtual DrillingProgramPart DrillingProgramPart { get; set; }
|
||||
|
||||
[ForeignKey(nameof(IdUser))]
|
||||
[InverseProperty(nameof(Model.User.RelationUsersUserRoles))]
|
||||
public virtual User User { get; set; }
|
||||
|
||||
}
|
||||
|
@ -64,5 +64,8 @@ namespace AsbCloudDb.Model
|
||||
|
||||
[InverseProperty(nameof(WellComposite.WellSrc))]
|
||||
public virtual ICollection<WellComposite> WellCompositeSrcs { get; set; }
|
||||
|
||||
[InverseProperty(nameof(DrillingProgramPart.Well))]
|
||||
public virtual ICollection<DrillingProgramPart> DrillingProgramParts { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="CommonLibs\" />
|
||||
<Folder Include="Services\DrillingProgram\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -13,6 +13,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.AspNetCore;
|
||||
using AsbCloudInfrastructure.Services.DrillingProgram;
|
||||
|
||||
namespace AsbCloudInfrastructure
|
||||
{
|
||||
|
@ -0,0 +1,178 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Services;
|
||||
using ClosedXML.Excel;
|
||||
using ClosedXML.Excel.Drawings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
{
|
||||
internal class DrillingProgramMaker
|
||||
{
|
||||
|
||||
private const int maxAllowedColumns = 256;
|
||||
|
||||
//public async Task<FileInfoDto> GetOrCreateAsync(int idWell, int idUser, CancellationToken token = default)
|
||||
//{
|
||||
// var programParts = (await fileService.GetInfosByCategoryAsync(idWell, idFileCategoryDrillingProgramItems, token)
|
||||
// .ConfigureAwait(false))
|
||||
// .Where(f => f.FileMarks?.Any(m => m.IdMarkType == 1 && !m.IsDeleted) ?? false);
|
||||
|
||||
// var well = await wellService.GetAsync(idWell, token)
|
||||
// .ConfigureAwait(false);
|
||||
|
||||
// var programs = await fileService.GetInfosByCategoryAsync(idWell, idFileCategoryDrillingProgram, token)
|
||||
// .ConfigureAwait(false);
|
||||
|
||||
// if (programs is not null && programs.Any() && programParts.Any())
|
||||
// {
|
||||
// programs = programs.OrderByDescending(f => f.UploadDate);
|
||||
// var matchFilesIterator = programs.GetEnumerator();
|
||||
// matchFilesIterator.MoveNext();
|
||||
// var matchFile = matchFilesIterator.Current;
|
||||
|
||||
// if (programParts.All(pp => matchFile.UploadDate > pp.UploadDate) &&
|
||||
// File.Exists(fileService.GetUrl(matchFile)))
|
||||
// return matchFile;
|
||||
// else
|
||||
// await fileService.DeleteAsync(matchFile.Id, token)
|
||||
// .ConfigureAwait(false);
|
||||
|
||||
// while (matchFilesIterator.MoveNext())
|
||||
// await fileService.DeleteAsync(matchFilesIterator.Current.Id, token)
|
||||
// .ConfigureAwait(false);
|
||||
// }
|
||||
|
||||
// if (!programParts.Any())
|
||||
// throw new FileNotFoundException("Нет частей для формирования программы бурения");
|
||||
|
||||
// var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.xlsx";
|
||||
|
||||
// var filteredFilePaths = programParts
|
||||
// .Select(file => fileService.GetUrl(file));
|
||||
|
||||
// var tempResultFilePath = Path.Combine(Path.GetTempPath(), "drillingProgram", resultFileName);
|
||||
|
||||
// UniteExcelFiles(filteredFilePaths, tempResultFilePath);
|
||||
|
||||
// var fileInfo = await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram,
|
||||
// resultFileName, tempResultFilePath, token).ConfigureAwait(false);
|
||||
|
||||
// return fileInfo;
|
||||
//}
|
||||
|
||||
private static void UniteExcelFiles(IEnumerable<string> excelFilesNames, string resultExcelPath)
|
||||
{
|
||||
var resultExcelFile = new XLWorkbook(XLEventTracking.Disabled);
|
||||
|
||||
var filteredFileNames = excelFilesNames.Distinct();
|
||||
|
||||
foreach (var excelFileName in filteredFileNames)
|
||||
{
|
||||
using var workbookSrc = new XLWorkbook(excelFileName, XLEventTracking.Disabled);
|
||||
|
||||
foreach (var sheet in workbookSrc.Worksheets)
|
||||
{
|
||||
if (sheet.Visibility == XLWorksheetVisibility.Visible)
|
||||
CopySheet(resultExcelFile, sheet);
|
||||
}
|
||||
}
|
||||
|
||||
resultExcelFile.SaveAs(resultExcelPath,
|
||||
new SaveOptions { EvaluateFormulasBeforeSaving = true });
|
||||
}
|
||||
|
||||
private static void CopySheet(XLWorkbook workbookDst, IXLWorksheet sheetSrc)
|
||||
{
|
||||
var newSheetName = sheetSrc.Name;
|
||||
var suffix = "";
|
||||
int index = 1;
|
||||
|
||||
while (workbookDst.Worksheets.Contains(newSheetName))
|
||||
{
|
||||
newSheetName = sheetSrc.Name;
|
||||
suffix = $"_{index++}";
|
||||
if (newSheetName.Length + suffix.Length >= 31)
|
||||
newSheetName = newSheetName[..(31 - suffix.Length)];
|
||||
newSheetName += suffix;
|
||||
}
|
||||
|
||||
var imagesInfos = sheetSrc.Pictures.Select(p => new ImageInfo
|
||||
{
|
||||
Id = p.Id,
|
||||
Data = p.ImageStream.GetBuffer(),
|
||||
Height = p.Height,
|
||||
Width = p.Width,
|
||||
TopLeftCellAddress = p.TopLeftCell.Address,
|
||||
Left = p.Left,
|
||||
Top = p.Top
|
||||
}).ToList();
|
||||
|
||||
IXLWorksheet resultSheet;
|
||||
|
||||
if (sheetSrc.Columns().Count() > maxAllowedColumns)
|
||||
{
|
||||
resultSheet = workbookDst.Worksheets.Add(newSheetName);
|
||||
|
||||
var rngData = GetCellsRange(sheetSrc);
|
||||
|
||||
rngData.CopyTo(resultSheet.Cell(1, 1));
|
||||
|
||||
var lastRowWithData = rngData.LastRowUsed().RangeAddress
|
||||
.LastAddress.RowNumber;
|
||||
|
||||
for (int i = 1; i < lastRowWithData; i++)
|
||||
{
|
||||
resultSheet.Row(i).Height = sheetSrc.Row(i).Height;
|
||||
resultSheet.Column(i).Width = sheetSrc.Column(i).Width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RemovePicturesFromSheet(sheetSrc);
|
||||
resultSheet = sheetSrc.CopyTo(workbookDst, newSheetName);
|
||||
}
|
||||
CopyImagesToAnotherSheet(imagesInfos, resultSheet);
|
||||
}
|
||||
|
||||
private static IXLWorksheet CopyImagesToAnotherSheet(IEnumerable<ImageInfo> imagesInfos,
|
||||
IXLWorksheet resultSheet)
|
||||
{
|
||||
foreach (var image in imagesInfos)
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
stream.Write(image.Data, 0, image.Data.Length);
|
||||
|
||||
resultSheet.AddPicture(stream)
|
||||
.WithPlacement(XLPicturePlacement.Move)
|
||||
.WithSize(image.Width, image.Height)
|
||||
.MoveTo(resultSheet.Cell(image.TopLeftCellAddress),
|
||||
image.Left, image.Top);
|
||||
}
|
||||
|
||||
return resultSheet;
|
||||
}
|
||||
|
||||
private static void RemovePicturesFromSheet(IXLWorksheet sheet)
|
||||
{
|
||||
var filteredPics = sheet.Pictures.Select(p => p.Name).Distinct().ToList();
|
||||
|
||||
foreach (var n in filteredPics)
|
||||
sheet.Pictures.Delete(n);
|
||||
}
|
||||
|
||||
private static IXLRange GetCellsRange(IXLWorksheet sheet)
|
||||
{
|
||||
var firstTableCell = sheet.FirstCellUsed();
|
||||
var lastTableCell = sheet.LastCellUsed();
|
||||
var rngData = sheet.Range(firstTableCell.Address, lastTableCell.Address);
|
||||
|
||||
return rngData;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,339 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
{
|
||||
public class DrillingProgramService : IDrillingProgramService
|
||||
{
|
||||
private readonly IAsbCloudDbContext context;
|
||||
private readonly IFileService fileService;
|
||||
private readonly IUserService userService;
|
||||
|
||||
private const int idFileCategoryDrillingProgram = 1000;
|
||||
private const int idFileCategoryDrillingProgramPartsStart = 1001;
|
||||
private const int idFileCategoryDrillingProgramPartsEnd = 1100;
|
||||
|
||||
private const int idPartStateNoFile = 0;
|
||||
private const int idPartStateApproving = 1;
|
||||
private const int idPartStateApproved = 2;
|
||||
|
||||
private const int idMarkTypeReject = 0;
|
||||
private const int idMarkTypeApprove = 1;
|
||||
|
||||
private const int idUserRolePublisher = 1;
|
||||
private const int idUserRoleApprover = 2;
|
||||
|
||||
private const int idStateNotInitialized = 0;
|
||||
private const int idStateApproving = 1;
|
||||
private const int idStateCreating = 2;
|
||||
private const int idStateReady = 3;
|
||||
|
||||
public DrillingProgramService(IAsbCloudDbContext context, IFileService fileService, IUserService userService)
|
||||
{
|
||||
this.context = context;
|
||||
this.fileService = fileService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileCategoryDto>> GetCategoriesAsync(CancellationToken token = default)
|
||||
{
|
||||
var result = await context.FileCategories
|
||||
.Where(c=>c.Id > idFileCategoryDrillingProgramPartsStart && c.Id < idFileCategoryDrillingProgramPartsEnd)
|
||||
.ToListAsync(token);
|
||||
return result.Select(c => c.Adapt<FileCategoryDto>());
|
||||
}
|
||||
|
||||
public async Task<DrillingProgramStateDto> GetStateAsync(int idWell, int idUser, CancellationToken token = default)
|
||||
{
|
||||
// Задание от геологов
|
||||
// Профиль ствола скважины(ННБ)
|
||||
// Технологические расчеты(ННБ)
|
||||
// Долотная программа
|
||||
// Программа по растворам
|
||||
// Программа геофизических исследований
|
||||
// Планы спусков обсадных колонн
|
||||
// Программы цементирования обсадных колонн
|
||||
|
||||
var fileCategories = await context.FileCategories
|
||||
.Where(c => c.Id >= idFileCategoryDrillingProgramPartsStart &&
|
||||
c.Id < idFileCategoryDrillingProgramPartsEnd)
|
||||
.ToListAsync(token);
|
||||
|
||||
var files = await context.Files
|
||||
.Include(f => f.FileMarks)
|
||||
.ThenInclude(m => m.User)
|
||||
.Include(f => f.Author)
|
||||
.Include(f => f.FileCategory)
|
||||
.Where(f => f.IdWell == idWell &&
|
||||
f.IdCategory >= idFileCategoryDrillingProgram &&
|
||||
f.IdCategory < idFileCategoryDrillingProgramPartsEnd &&
|
||||
f.IsDeleted == false)
|
||||
.OrderBy(f => f.UploadDate)
|
||||
.ToListAsync(token);
|
||||
|
||||
var partEntities = await context.DrillingProgramParts
|
||||
.Include(p => p.RelatedUsers)
|
||||
.ThenInclude(r => r.User)
|
||||
.Where(p => p.IdWell == idWell)
|
||||
.ToListAsync(token);
|
||||
|
||||
var parts = new List<DrillingProgramPartDto>(partEntities.Count);
|
||||
|
||||
foreach (var partEntity in partEntities)
|
||||
{
|
||||
var part = ConvertPart(idUser, fileCategories, files, partEntity);
|
||||
parts.Add(part);
|
||||
}
|
||||
|
||||
var state = new DrillingProgramStateDto();
|
||||
state.Parts = parts;
|
||||
state.Program = files.FirstOrDefault(f => f.IdCategory == idFileCategoryDrillingProgram)
|
||||
.Adapt<FileInfoDto>();
|
||||
|
||||
if (parts.Any())
|
||||
{
|
||||
if(parts.All(p=>p.IdState == idPartStateApproved))
|
||||
{
|
||||
if (state.Program is not null)
|
||||
state.IdState = idStateReady;
|
||||
else
|
||||
state.IdState = idStateCreating;
|
||||
}
|
||||
else
|
||||
state.IdState = idStateApproving;
|
||||
}
|
||||
else
|
||||
state.IdState = idStateNotInitialized;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public async Task<int> AddFile(int idPart, int idUser, string fileFullName, System.IO.Stream fileStream, CancellationToken token = default)
|
||||
{
|
||||
var part = await context.DrillingProgramParts
|
||||
.Include(p => p.RelatedUsers)
|
||||
.FirstOrDefaultAsync(p => p.Id == idPart);
|
||||
|
||||
if (part == null)
|
||||
throw new ArgumentInvalidException($"DrillingProgramPart id == {idPart} does not exist", nameof(idPart));
|
||||
|
||||
if (! part.RelatedUsers.Any(r => r.IdUser == idUser && r.IdUserRole == idUserRolePublisher))
|
||||
throw new ForbidException($"User {idUser} is not in the publisher list.");
|
||||
|
||||
var result = await fileService.SaveAsync(
|
||||
part.IdWell,
|
||||
idUser,
|
||||
part.IdFileCategory,
|
||||
fileFullName,
|
||||
fileStream,
|
||||
token);
|
||||
|
||||
await RemoveDrillingProgramAsync(part.IdWell, token);
|
||||
return result.Id;
|
||||
}
|
||||
|
||||
public async Task<int> AddPartAsync(int idWell, int idFileCategory, CancellationToken token = default)
|
||||
{
|
||||
var part = new DrillingProgramPart
|
||||
{
|
||||
IdWell = idWell,
|
||||
IdFileCategory = idFileCategory,
|
||||
};
|
||||
var entry = context.DrillingProgramParts.Add(part);
|
||||
await context.SaveChangesAsync(token);
|
||||
|
||||
await RemoveDrillingProgramAsync(part.IdWell, token);
|
||||
return entry.Entity.Id;
|
||||
}
|
||||
|
||||
public async Task<int> RemovePartAsync(int idWell, int idFileCategory, CancellationToken token = default)
|
||||
{
|
||||
var whereQuery = context.DrillingProgramParts
|
||||
.Where(r => r.IdWell == idWell &&
|
||||
r.IdFileCategory == idFileCategory);
|
||||
|
||||
context.DrillingProgramParts.RemoveRange(whereQuery);
|
||||
|
||||
await RemoveDrillingProgramAsync(idWell, token);
|
||||
return await context.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public async Task<int> AddUserAsync(int idUser, int idPart, int idUserRole, CancellationToken token = default)
|
||||
{
|
||||
var user = await userService.GetAsync(idUser, token);
|
||||
if (user is null)
|
||||
throw new ArgumentInvalidException($"User id == {idUser} does not exist", nameof(idUser));
|
||||
|
||||
var drillingProgramPart = await context.DrillingProgramParts.FirstOrDefaultAsync(p => p.Id == idPart, token);
|
||||
if (drillingProgramPart is null)
|
||||
throw new ArgumentInvalidException($"DrillingProgramPart id == {idPart} does not exist", nameof(idPart));
|
||||
|
||||
if (idUserRole != idUserRoleApprover && idUserRole != idUserRolePublisher)
|
||||
throw new ArgumentInvalidException($"idUserRole ({idPart}), should be approver ({idUserRoleApprover}) or publisher({idUserRolePublisher})", nameof(idPart));
|
||||
|
||||
var newRelation = new RelationUserDrillingProgramPart
|
||||
{
|
||||
IdUser = idUser,
|
||||
IdDrillingProgramPart = idPart,
|
||||
IdUserRole = idUserRole,
|
||||
};
|
||||
|
||||
context.RelationDrillingProgramPartUsers.Add(newRelation);
|
||||
if(idUserRole == idUserRoleApprover)
|
||||
await RemoveDrillingProgramAsync(drillingProgramPart.IdWell, token);
|
||||
return await context.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public async Task<int> RemoveUserAsync(int idUser, int idPart, int idUserRole, CancellationToken token = default)
|
||||
{
|
||||
var whereQuery = context.RelationDrillingProgramPartUsers
|
||||
.Where(r => r.IdUser == idUser &&
|
||||
r.IdDrillingProgramPart == idPart &&
|
||||
r.IdUserRole == idUserRole);
|
||||
|
||||
context.RelationDrillingProgramPartUsers.RemoveRange(whereQuery);
|
||||
if (idUserRole == idUserRoleApprover)
|
||||
{
|
||||
var part = await context.DrillingProgramParts.FirstOrDefaultAsync(p => p.Id == idPart, token);
|
||||
await CheckAndEnqueueMakeProgramAsync(part.IdWell, token);
|
||||
}
|
||||
|
||||
return await context.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public async Task<int> AddOrReplaceFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token)
|
||||
{
|
||||
if(fileMarkDto.IdMarkType != idMarkTypeApprove &&
|
||||
fileMarkDto.IdMarkType != idMarkTypeReject)
|
||||
throw new ArgumentInvalidException($"В этом методе допустимы только отметки о принятии или отклонении.", nameof(fileMarkDto));
|
||||
|
||||
var fileInfo = await fileService.GetInfoAsync(fileMarkDto.IdFile, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (fileInfo is null)
|
||||
throw new ArgumentInvalidException($"Файла для такой отметки не существует.", nameof(fileMarkDto));
|
||||
|
||||
if (fileInfo.IdCategory < idFileCategoryDrillingProgramPartsStart ||
|
||||
fileInfo.IdCategory > idFileCategoryDrillingProgramPartsEnd)
|
||||
throw new ArgumentInvalidException($"Этот метод допустим только для файлов-частей программы бурения.", nameof(fileMarkDto));
|
||||
|
||||
var part = await context.DrillingProgramParts
|
||||
.FirstOrDefaultAsync(p => p.IdWell == fileInfo.IdWell && p.IdFileCategory == fileInfo.IdCategory, token);
|
||||
|
||||
if (!part.RelatedUsers.Any(r => r.IdUser == idUser && r.IdUserRole == idUserRoleApprover))
|
||||
throw new ForbidException($"User {idUser} is not in the approvers list.");
|
||||
|
||||
var oldMarksIds = fileInfo.FileMarks
|
||||
?.Where(m => m.User.Id == idUser)
|
||||
.Select(m => m.Id);
|
||||
|
||||
if(oldMarksIds?.Any() == true)
|
||||
await fileService.MarkFileMarkAsDeletedAsync(oldMarksIds, token);
|
||||
|
||||
var result = await fileService.CreateFileMarkAsync(fileMarkDto, idUser, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if(fileMarkDto.IdMarkType == idMarkTypeApprove)
|
||||
await CheckAndEnqueueMakeProgramAsync(fileInfo.IdWell, token);
|
||||
else
|
||||
await RemoveDrillingProgramAsync(fileInfo.IdWell, token);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<int> MarkAsDeletedFileMarkAsync(int idMark,
|
||||
CancellationToken token)
|
||||
{
|
||||
var fileInfo = await fileService.GetByMarkId(idMark, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (fileInfo.IdCategory < idFileCategoryDrillingProgramPartsStart ||
|
||||
fileInfo.IdCategory > idFileCategoryDrillingProgramPartsEnd)
|
||||
throw new ArgumentInvalidException($"Этот метод допустим только для файлов-частей программы бурения.", nameof(idMark));
|
||||
|
||||
var result = await fileService.MarkFileMarkAsDeletedAsync(idMark, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
await RemoveDrillingProgramAsync(fileInfo.IdWell, token);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static DrillingProgramPartDto ConvertPart(int idUser, List<FileCategory> fileCategories, List<FileInfo> files, DrillingProgramPart partEntity)
|
||||
{
|
||||
var part = new DrillingProgramPartDto
|
||||
{
|
||||
IdFileCategory = partEntity.IdFileCategory,
|
||||
Name = fileCategories.FirstOrDefault(c => c.Id == partEntity.IdFileCategory).Name,
|
||||
Approvers = partEntity.RelatedUsers
|
||||
.Where(u => u.IdUserRole == idUserRoleApprover)
|
||||
.Select(u => u.Adapt<UserDto>()),
|
||||
Publishers = partEntity.RelatedUsers
|
||||
.Where(u => u.IdUserRole == idUserRolePublisher)
|
||||
.Select(u => u.Adapt<UserDto>()),
|
||||
PermissionToApprove = partEntity.RelatedUsers
|
||||
.Any(u => u.IdUserRole == idUserRoleApprover && u.IdUser == idUser),
|
||||
PermissionToUpload = partEntity.RelatedUsers
|
||||
.Any(u => u.IdUserRole == idUserRolePublisher && u.IdUser == idUser),
|
||||
};
|
||||
|
||||
var fileEntity = files.LastOrDefault(f => f.IdCategory == partEntity.IdFileCategory);
|
||||
|
||||
if (fileEntity is not null)
|
||||
{
|
||||
part.File = fileEntity.Adapt<FileInfoDto>();
|
||||
var marks = fileEntity.FileMarks.Where(m => !m.IsDeleted);
|
||||
|
||||
if (marks.Any())
|
||||
{
|
||||
var hasReject = marks.Any(m => m.IdMarkType == idMarkTypeReject);
|
||||
if (!hasReject)
|
||||
{
|
||||
var allAproved = part.Approvers.All(a => marks.Any(m => m.IdUser == a.Id && m.IdMarkType == idMarkTypeApprove));
|
||||
if (allAproved)
|
||||
part.IdState = idPartStateApproved;
|
||||
}
|
||||
}
|
||||
else
|
||||
part.IdState = idPartStateApproving;
|
||||
}
|
||||
else
|
||||
part.IdState = idPartStateNoFile;
|
||||
|
||||
return part;
|
||||
}
|
||||
|
||||
private async Task CheckAndEnqueueMakeProgramAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var state = await GetStateAsync(idWell, 0, token);
|
||||
if(state.IdState == idStateCreating)
|
||||
{
|
||||
// TODO: check if task is running else enqueue task
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<int> RemoveDrillingProgramAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
// TODO: dequeue task if it exist
|
||||
var filesIds = await context.Files
|
||||
.Where(f => f.IdWell == idWell &&
|
||||
f.IdCategory == idFileCategoryDrillingProgram)
|
||||
.Select(f => f.Id)
|
||||
.ToListAsync(token);
|
||||
if (filesIds.Any())
|
||||
return await fileService.DeleteAsync(filesIds, token);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
15
AsbCloudInfrastructure/Services/DrillingProgram/ImageInfo.cs
Normal file
15
AsbCloudInfrastructure/Services/DrillingProgram/ImageInfo.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using ClosedXML.Excel;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
{
|
||||
class ImageInfo
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
public int Height { get; set; }
|
||||
public int Width { get; set; }
|
||||
public IXLAddress TopLeftCellAddress { get; set; }
|
||||
public int Left { get; set; }
|
||||
public int Top { get; set; }
|
||||
}
|
||||
}
|
@ -1,256 +0,0 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Services;
|
||||
using ClosedXML.Excel;
|
||||
using ClosedXML.Excel.Drawings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
public class DrillingProgramService : IDrillingProgramService
|
||||
{
|
||||
private readonly IFileService fileService;
|
||||
private readonly IWellService wellService;
|
||||
private const int idFileCategoryDrillingProgramItems = 13;
|
||||
private const int idFileCategoryDrillingProgram = 14;
|
||||
|
||||
private const int maxAllowedColumns = 256;
|
||||
|
||||
public DrillingProgramService(IFileService fileService, IWellService wellService)
|
||||
{
|
||||
this.fileService = fileService;
|
||||
this.wellService = wellService;
|
||||
}
|
||||
|
||||
public async Task<string> GetOrCreateSharedUrlAsync(int idWell, int idUser, IFileShareService fileShareService, CancellationToken token = default)
|
||||
{
|
||||
var fileInfo = await GetOrCreateAsync(idWell, idUser, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (fileInfo is null)
|
||||
return null;
|
||||
|
||||
var sharedUrl = await fileService.GetSharedUrlAsync(fileInfo, idUser, fileShareService, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return sharedUrl;
|
||||
}
|
||||
|
||||
public async Task<FileInfoDto> GetOrCreateAsync(int idWell, int idUser, CancellationToken token = default)
|
||||
{
|
||||
var programParts = (await fileService.GetInfosByCategoryAsync(idWell, idFileCategoryDrillingProgramItems, token)
|
||||
.ConfigureAwait(false))
|
||||
.Where(f => f.FileMarks?.Any(m => m.IdMarkType == 1 && !m.IsDeleted)??false);
|
||||
|
||||
var well = await wellService.GetAsync(idWell, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var programs = await fileService.GetInfosByCategoryAsync(idWell, idFileCategoryDrillingProgram, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (programs is not null && programs.Any() && programParts.Any())
|
||||
{
|
||||
programs = programs.OrderByDescending(f => f.UploadDate);
|
||||
var matchFilesIterator = programs.GetEnumerator();
|
||||
matchFilesIterator.MoveNext();
|
||||
var matchFile = matchFilesIterator.Current;
|
||||
|
||||
if (programParts.All(pp => matchFile.UploadDate > pp.UploadDate) &&
|
||||
File.Exists(fileService.GetUrl(matchFile)))
|
||||
return matchFile;
|
||||
else
|
||||
await fileService.DeleteAsync(matchFile.Id, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
while (matchFilesIterator.MoveNext())
|
||||
await fileService.DeleteAsync(matchFilesIterator.Current.Id, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!programParts.Any())
|
||||
throw new FileNotFoundException("Нет частей для формирования программы бурения");
|
||||
|
||||
var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.xlsx";
|
||||
|
||||
var filteredFilePaths = programParts
|
||||
.Select(file => fileService.GetUrl(file));
|
||||
|
||||
var tempResultFilePath = Path.Combine(Path.GetTempPath(), "drillingProgram", resultFileName);
|
||||
|
||||
UniteExcelFiles(filteredFilePaths, tempResultFilePath);
|
||||
|
||||
var fileInfo = await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram,
|
||||
resultFileName, tempResultFilePath, token).ConfigureAwait(false);
|
||||
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
public async Task<int> CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token)
|
||||
{
|
||||
var fileInfo = await fileService.GetInfoAsync(fileMarkDto.IdFile, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (fileInfo.IdCategory != idFileCategoryDrillingProgramItems)
|
||||
throw new ArgumentInvalidException($"Этот метод допустим только для файлов-частей программы бурения idCategory=={idFileCategoryDrillingProgramItems}.", nameof(fileMarkDto));
|
||||
|
||||
var result = await fileService.CreateFileMarkAsync(fileMarkDto, idUser, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var drillingPrograms = await fileService.GetInfosByCategoryAsync(fileInfo.IdWell, idFileCategoryDrillingProgram, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
foreach (var drillingProgram in drillingPrograms)
|
||||
await fileService.DeleteAsync(drillingProgram.Id, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<int> MarkFileMarkAsDeletedAsync(int idMark,
|
||||
CancellationToken token)
|
||||
{
|
||||
var fileInfo = await fileService.GetByMarkId(idMark, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (fileInfo.IdCategory != idFileCategoryDrillingProgramItems)
|
||||
throw new ArgumentInvalidException($"Этот метод допустим только для файлов-частей программы бурения idCategory=={idFileCategoryDrillingProgramItems}.", nameof(idMark));
|
||||
|
||||
var result = await fileService.MarkFileMarkAsDeletedAsync(idMark, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var drillingPrograms = await fileService.GetInfosByCategoryAsync(fileInfo.IdWell, idFileCategoryDrillingProgram, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
foreach (var drillingProgram in drillingPrograms)
|
||||
await fileService.DeleteAsync(drillingProgram.Id, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void UniteExcelFiles(IEnumerable<string> excelFilesNames, string resultExcelPath)
|
||||
{
|
||||
var resultExcelFile = new XLWorkbook(XLEventTracking.Disabled);
|
||||
|
||||
var filteredFileNames = excelFilesNames.Distinct();
|
||||
|
||||
foreach (var excelFileName in filteredFileNames)
|
||||
{
|
||||
using var workbookSrc = new XLWorkbook(excelFileName, XLEventTracking.Disabled);
|
||||
|
||||
foreach (var sheet in workbookSrc.Worksheets)
|
||||
{
|
||||
if(sheet.Visibility == XLWorksheetVisibility.Visible)
|
||||
CopySheet(resultExcelFile, sheet);
|
||||
}
|
||||
}
|
||||
|
||||
resultExcelFile.SaveAs(resultExcelPath,
|
||||
new SaveOptions { EvaluateFormulasBeforeSaving = true});
|
||||
}
|
||||
|
||||
private static void CopySheet(XLWorkbook workbookDst, IXLWorksheet sheetSrc)
|
||||
{
|
||||
var newSheetName = sheetSrc.Name;
|
||||
var suffix = "";
|
||||
int index = 1;
|
||||
|
||||
while (workbookDst.Worksheets.Contains(newSheetName))
|
||||
{
|
||||
newSheetName = sheetSrc.Name;
|
||||
suffix = $"_{index++}";
|
||||
if (newSheetName.Length + suffix.Length >= 31)
|
||||
newSheetName = newSheetName[..(31 - suffix.Length)];
|
||||
newSheetName += suffix;
|
||||
}
|
||||
|
||||
var imagesInfos = sheetSrc.Pictures.Select(p => new ImageInfo
|
||||
{
|
||||
Id = p.Id,
|
||||
Data = p.ImageStream.GetBuffer(),
|
||||
Height = p.Height,
|
||||
Width = p.Width,
|
||||
TopLeftCellAddress = p.TopLeftCell.Address,
|
||||
Left = p.Left,
|
||||
Top = p.Top
|
||||
}).ToList();
|
||||
|
||||
IXLWorksheet resultSheet;
|
||||
|
||||
if (sheetSrc.Columns().Count() > maxAllowedColumns)
|
||||
{
|
||||
resultSheet = workbookDst.Worksheets.Add(newSheetName);
|
||||
|
||||
var rngData = GetCellsRange(sheetSrc);
|
||||
|
||||
rngData.CopyTo(resultSheet.Cell(1, 1));
|
||||
|
||||
var lastRowWithData = rngData.LastRowUsed().RangeAddress
|
||||
.LastAddress.RowNumber;
|
||||
|
||||
for (int i = 1; i < lastRowWithData; i++)
|
||||
{
|
||||
resultSheet.Row(i).Height = sheetSrc.Row(i).Height;
|
||||
resultSheet.Column(i).Width = sheetSrc.Column(i).Width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RemovePicturesFromSheet(sheetSrc);
|
||||
resultSheet = sheetSrc.CopyTo(workbookDst, newSheetName);
|
||||
}
|
||||
CopyImagesToAnotherSheet(imagesInfos, resultSheet);
|
||||
}
|
||||
|
||||
private static IXLWorksheet CopyImagesToAnotherSheet(IEnumerable<ImageInfo> imagesInfos,
|
||||
IXLWorksheet resultSheet)
|
||||
{
|
||||
foreach (var image in imagesInfos)
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
stream.Write(image.Data, 0, image.Data.Length);
|
||||
|
||||
resultSheet.AddPicture(stream)
|
||||
.WithPlacement(XLPicturePlacement.Move)
|
||||
.WithSize(image.Width, image.Height)
|
||||
.MoveTo(resultSheet.Cell(image.TopLeftCellAddress),
|
||||
image.Left, image.Top);
|
||||
}
|
||||
|
||||
return resultSheet;
|
||||
}
|
||||
|
||||
private static void RemovePicturesFromSheet(IXLWorksheet sheet)
|
||||
{
|
||||
var filteredPics = sheet.Pictures.Select(p => p.Name).Distinct().ToList();
|
||||
|
||||
foreach (var n in filteredPics)
|
||||
sheet.Pictures.Delete(n);
|
||||
}
|
||||
|
||||
private static IXLRange GetCellsRange(IXLWorksheet sheet)
|
||||
{
|
||||
var firstTableCell = sheet.FirstCellUsed();
|
||||
var lastTableCell = sheet.LastCellUsed();
|
||||
var rngData = sheet.Range(firstTableCell.Address, lastTableCell.Address);
|
||||
|
||||
return rngData;
|
||||
}
|
||||
}
|
||||
|
||||
class ImageInfo
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
public int Height { get; set; }
|
||||
public int Width { get; set; }
|
||||
public IXLAddress TopLeftCellAddress { get; set; }
|
||||
public int Left { get; set; }
|
||||
public int Top { get; set; }
|
||||
}
|
||||
}
|
@ -246,20 +246,31 @@ namespace AsbCloudInfrastructure.Services
|
||||
return await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<int> DeleteAsync(int idFile, CancellationToken token)
|
||||
{
|
||||
var fileInfo = await db.Files
|
||||
.FirstOrDefaultAsync(f => f.Id == idFile, token)
|
||||
.ConfigureAwait(false);
|
||||
public Task<int> DeleteAsync(int idFile, CancellationToken token)
|
||||
=> DeleteAsync(new int[] { idFile}, token);
|
||||
|
||||
if (fileInfo is null)
|
||||
public async Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token)
|
||||
{
|
||||
if (ids is null || !ids.Any())
|
||||
return 0;
|
||||
|
||||
var fileName = GetUrl(fileInfo.Adapt<FileInfoDto>());
|
||||
if (File.Exists(fileName))
|
||||
File.Delete(fileName);
|
||||
var filesQuery = db.Files
|
||||
.Where(f => ids.Contains(f.Id));
|
||||
|
||||
var files = await filesQuery.ToListAsync(token);
|
||||
|
||||
if (files is null || !files.Any())
|
||||
return 0;
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
var fileName = GetUrl(file.IdWell, file.IdCategory, file.Id, Path.GetExtension(file.Name));
|
||||
if (File.Exists(fileName))
|
||||
File.Delete(fileName);
|
||||
}
|
||||
|
||||
db.Files.RemoveRange(filesQuery);
|
||||
|
||||
db.Files.Remove(fileInfo);
|
||||
return await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@ -330,16 +341,22 @@ namespace AsbCloudInfrastructure.Services
|
||||
db.FileMarks.Add(newFileMark);
|
||||
return await db.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public async Task<int> MarkFileMarkAsDeletedAsync(int idMark,
|
||||
|
||||
public Task<int> MarkFileMarkAsDeletedAsync(int idMark,
|
||||
CancellationToken token)
|
||||
=> MarkFileMarkAsDeletedAsync(new int[] { idMark }, token);
|
||||
|
||||
public async Task<int> MarkFileMarkAsDeletedAsync(IEnumerable<int> idsMarks,
|
||||
CancellationToken token)
|
||||
{
|
||||
var fileMark = await db.FileMarks
|
||||
.FirstOrDefaultAsync(m => m.Id == idMark, token)
|
||||
.ConfigureAwait(false);
|
||||
fileMark.IsDeleted = true;
|
||||
var fileMarkQuery = db.FileMarks
|
||||
.Where(m => idsMarks.Contains( m.Id ));
|
||||
|
||||
foreach (var fileMark in fileMarkQuery)
|
||||
fileMark.IsDeleted = true;
|
||||
|
||||
return await db.SaveChangesAsync(token);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<int> SaveWeblinkToFileInfo(int idFileInfo, int idUser, string weblink,
|
||||
CancellationToken token)
|
||||
|
@ -1,6 +1,5 @@
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services.Cache;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
@ -1,8 +1,12 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -24,54 +28,30 @@ namespace AsbCloudWebApi.Controllers
|
||||
this.fileService = fileService;
|
||||
this.wellService = wellService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Список категорий файлов из которых состоит программа бурения
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("categories")]
|
||||
[ProducesResponseType(typeof(FileCategoryDto[]), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> GetCategories(CancellationToken token)
|
||||
{
|
||||
var result = await drillingProgramService.GetCategoriesAsync(token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает программу бурения
|
||||
/// Состояние процесса согласования программы бурения
|
||||
/// </summary>
|
||||
/// <param name="idWell"> id скважины </param>
|
||||
/// <param name="token"> Токен отмены задачи </param>
|
||||
/// <returns> Возвращает файл программы бурения </returns>
|
||||
[HttpGet]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(FileResult), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> GetAsync(int idWell, CancellationToken token = default)
|
||||
{
|
||||
var idCompany = User.GetCompanyId();
|
||||
|
||||
var fileChangerId = User.GetUserId();
|
||||
|
||||
if (idCompany is null || fileChangerId is null ||
|
||||
!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
try
|
||||
{
|
||||
var fileInfo = await drillingProgramService.GetOrCreateAsync(idWell,
|
||||
(int)fileChangerId, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var relativePath = fileService.GetUrl(fileInfo);
|
||||
|
||||
return PhysicalFile(Path.GetFullPath(relativePath), "application/octet-stream", fileInfo.Name);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
return NotFound(ex.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает программу бурения
|
||||
/// </summary>
|
||||
/// <param name="idWell"> id скважины </param>
|
||||
/// <param name="fileShareService"></param>
|
||||
/// <param name="token"> Токен отмены задачи </param>
|
||||
/// <returns> Возвращает ссылку на файл программы бурения в облаке </returns>
|
||||
[HttpGet("webUrl")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(string), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> GetOrCreateSharedUrlAsync(int idWell, [FromServices]IFileShareService fileShareService, CancellationToken token = default)
|
||||
[ProducesResponseType(typeof(DrillingProgramStateDto), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> GetStateAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var idCompany = User.GetCompanyId();
|
||||
|
||||
@ -81,16 +61,143 @@ namespace AsbCloudWebApi.Controllers
|
||||
!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
var sharedUrl = await drillingProgramService.GetOrCreateSharedUrlAsync(idWell,
|
||||
(int)idUser, fileShareService, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Ok(sharedUrl);
|
||||
|
||||
var result = await drillingProgramService.GetStateAsync(idWell, (int)idUser, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает метку для файла входящего в программу бурения
|
||||
/// Загрузка файла программы бурения
|
||||
/// </summary>
|
||||
/// <param name="idPart">ID части программы. Не путать с категорией файла</param>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="files"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("{idPart}")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(Task<int>), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> AddFile(
|
||||
int idPart,
|
||||
int idWell,
|
||||
[FromForm] IFormFileCollection files,
|
||||
CancellationToken token)
|
||||
{
|
||||
int? idCompany = User.GetCompanyId();
|
||||
int? idUser = User.GetUserId();
|
||||
|
||||
if (idCompany is null || idUser is null)
|
||||
return Forbid();
|
||||
|
||||
if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
if (files.Count > 1)
|
||||
return BadRequest(ArgumentInvalidException.MakeValidationError(nameof(files), "only 1 file can be uploaded"));
|
||||
|
||||
if (files.Count == 0)
|
||||
return BadRequest(ArgumentInvalidException.MakeValidationError(nameof(files), "at list 1 file can be uploaded"));
|
||||
|
||||
var fileName = files[0].FileName;
|
||||
var fileStream = files[0].OpenReadStream();
|
||||
var result = await drillingProgramService.AddFile(idPart, (int)idUser, fileName, fileStream, token);
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавить раздел программы бурения
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idFileCategory"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("part")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(Task<int>), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> AddPartAsync(int idWell, int idFileCategory, CancellationToken token)
|
||||
{
|
||||
int? idCompany = User.GetCompanyId();
|
||||
int? idUser = User.GetUserId();
|
||||
|
||||
if (idCompany is null || idUser is null)
|
||||
return Forbid();
|
||||
|
||||
if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
var result = drillingProgramService.AddPartAsync(idWell, idFileCategory, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удалить раздел программы бурения
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idFileCategory"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("part")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(Task<int>), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> RemovePartAsync(int idWell, int idFileCategory, CancellationToken token)
|
||||
{
|
||||
int? idCompany = User.GetCompanyId();
|
||||
int? idUser = User.GetUserId();
|
||||
|
||||
if (idCompany is null || idUser is null)
|
||||
return Forbid();
|
||||
|
||||
if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
var result = drillingProgramService.RemovePartAsync(idWell, idFileCategory, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("part/{idPart}/user/{idUser}")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(Task<int>), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> AddUserAsync(int idWell, int idUser, int idPart, int idUserRole, CancellationToken token = default)
|
||||
{
|
||||
int? idCompany = User.GetCompanyId();
|
||||
int? idUserEditor = User.GetUserId();
|
||||
|
||||
if (idCompany is null || idUserEditor is null)
|
||||
return Forbid();
|
||||
|
||||
if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
var result = drillingProgramService.AddUserAsync(idUser, idPart, idUserRole, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpDelete("part/{idPart}/user/{idUser}")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(Task<int>), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> RemoveUserAsync(int idWell, int idUser, int idPart, int idUserRole, CancellationToken token = default)
|
||||
{
|
||||
int? idCompany = User.GetCompanyId();
|
||||
int? idUserEditor = User.GetUserId();
|
||||
|
||||
if (idCompany is null || idUserEditor is null)
|
||||
return Forbid();
|
||||
|
||||
if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
var result = drillingProgramService.RemoveUserAsync(idUser, idPart, idUserRole, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает метку для файла входящего в программу бурения, заменить существующую
|
||||
/// </summary>
|
||||
/// <param name="idWell"> id скважины </param>
|
||||
/// <param name="markDto">метка файла</param>
|
||||
@ -98,7 +205,7 @@ namespace AsbCloudWebApi.Controllers
|
||||
/// <returns></returns>
|
||||
[HttpPost("fileMark")]
|
||||
[Permission]
|
||||
public async Task<IActionResult> CreateFileMarkAsync(int idWell, FileMarkDto markDto, CancellationToken token = default)
|
||||
public async Task<IActionResult> AddOrReplaceFileMarkAsync(int idWell, FileMarkDto markDto, CancellationToken token)
|
||||
{
|
||||
var idCompany = User.GetCompanyId();
|
||||
|
||||
@ -109,7 +216,7 @@ namespace AsbCloudWebApi.Controllers
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
var result = await drillingProgramService.CreateFileMarkAsync(markDto, (int)idUser, token)
|
||||
var result = await drillingProgramService.AddOrReplaceFileMarkAsync(markDto, (int)idUser, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Ok(result);
|
||||
@ -125,8 +232,8 @@ namespace AsbCloudWebApi.Controllers
|
||||
[HttpDelete("fileMark")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> DeleteFileMarkAsync(int idWell, int idMark,
|
||||
CancellationToken token = default)
|
||||
public async Task<IActionResult> MarkAsDeletedFileMarkAsync(int idWell, int idMark,
|
||||
CancellationToken token)
|
||||
{
|
||||
var idCompany = User.GetCompanyId();
|
||||
|
||||
@ -134,7 +241,7 @@ namespace AsbCloudWebApi.Controllers
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
var result = await drillingProgramService.MarkFileMarkAsDeletedAsync(idMark, token)
|
||||
var result = await drillingProgramService.MarkAsDeletedFileMarkAsync(idMark, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Ok(result);
|
||||
|
@ -53,13 +53,6 @@ namespace AsbCloudWebApi.Controllers
|
||||
if(!userService.HasPermission((int)idUser, $"File.edit{idCategory}"))
|
||||
return Forbid();
|
||||
|
||||
var fileInfoCollection = files.Select(f => new FileInfoDto
|
||||
{
|
||||
Name = f.FileName,
|
||||
IdCategory = idCategory,
|
||||
UploadDate = DateTime.Now
|
||||
});
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
var fileStream = file.OpenReadStream();
|
||||
|
@ -3,7 +3,7 @@ using System.Security.Claims;
|
||||
|
||||
namespace AsbCloudWebApi
|
||||
{
|
||||
public static class Extensions
|
||||
public static class Extentions
|
||||
{
|
||||
public static int? GetCompanyId(this ClaimsPrincipal user)
|
||||
{
|
@ -30,6 +30,12 @@ namespace AsbCloudWebApi.Middlewares
|
||||
var body = MakeJsonBody(ex);
|
||||
await context.Response.WriteAsync(body);
|
||||
}
|
||||
catch(ForbidException ex)
|
||||
{
|
||||
Console.WriteLine($"ForbidException in {context.Request.Method}: {ex.Message}");
|
||||
context.Response.Clear();
|
||||
context.Response.StatusCode = 403;
|
||||
}
|
||||
catch (TaskCanceledException ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
@ -45,7 +51,7 @@ namespace AsbCloudWebApi.Middlewares
|
||||
|
||||
private static string MakeJsonBody(ArgumentInvalidException ex)
|
||||
{
|
||||
object error = new { name = ex.ParamName, errors = new string[] { ex.Message } };
|
||||
object error = ex.ToValaidationErrorObject();
|
||||
var buffer = System.Text.Json.JsonSerializer.Serialize(error);
|
||||
return buffer;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user