2022-02-12 11:28:16 +05:00
using AsbCloudApp.Data ;
using AsbCloudApp.Exceptions ;
2022-10-27 11:22:39 +05:00
using AsbCloudApp.Repositories ;
2022-02-12 11:28:16 +05:00
using AsbCloudApp.Services ;
using AsbCloudDb.Model ;
2022-12-02 14:48:23 +05:00
using AsbCloudInfrastructure.Background ;
2023-01-13 17:28:04 +05:00
using AsbCloudInfrastructure.Services.DrillingProgram.Convert ;
2022-02-12 11:28:16 +05:00
using Mapster ;
using Microsoft.EntityFrameworkCore ;
2022-02-17 15:37:27 +05:00
using Microsoft.Extensions.Configuration ;
2022-12-02 14:48:23 +05:00
using Microsoft.Extensions.DependencyInjection ;
2022-02-12 11:28:16 +05:00
using System ;
using System.Collections.Generic ;
2022-02-17 15:37:27 +05:00
using System.IO ;
2022-02-12 11:28:16 +05:00
using System.Linq ;
using System.Threading ;
using System.Threading.Tasks ;
namespace AsbCloudInfrastructure.Services.DrillingProgram
{
2022-12-02 14:48:23 +05:00
# nullable enable
2022-02-12 11:28:16 +05:00
public class DrillingProgramService : IDrillingProgramService
{
2022-03-02 16:21:07 +05:00
private static readonly Dictionary < string , DrillingProgramCreateError > drillingProgramCreateErrors = new Dictionary < string , DrillingProgramCreateError > ( ) ;
2022-02-28 14:44:15 +05:00
2022-02-12 11:28:16 +05:00
private readonly IAsbCloudDbContext context ;
2022-10-06 14:37:03 +05:00
private readonly FileService fileService ;
2022-10-27 11:22:39 +05:00
private readonly IUserRepository userRepository ;
2022-02-17 15:37:27 +05:00
private readonly IWellService wellService ;
2022-02-28 14:44:15 +05:00
private readonly IConfiguration configuration ;
2022-12-02 14:48:23 +05:00
private readonly BackgroundWorker backgroundWorker ;
2023-01-25 05:41:29 +05:00
private readonly IEmailService emailService ;
2022-02-12 11:28:16 +05:00
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 ;
2022-02-28 14:44:15 +05:00
private const int idStateError = 4 ;
2022-02-12 11:28:16 +05:00
2023-01-26 15:25:09 +05:00
private static readonly string [ ] filePermittedExt = { ".xlsx" , ".xls" , ".ods" , ".odt" , ".doc" , ".docx" , ".pdf" } ;
2022-02-17 15:37:27 +05:00
public DrillingProgramService (
2022-04-11 18:00:34 +05:00
IAsbCloudDbContext context ,
2022-10-06 14:37:03 +05:00
FileService fileService ,
2022-10-27 11:22:39 +05:00
IUserRepository userRepository ,
2022-02-17 15:37:27 +05:00
IWellService wellService ,
IConfiguration configuration ,
2022-12-02 14:48:23 +05:00
BackgroundWorker backgroundWorker ,
2023-01-25 05:41:29 +05:00
IEmailService emailService )
2022-06-15 14:57:37 +05:00
{
2022-02-12 11:28:16 +05:00
this . context = context ;
this . fileService = fileService ;
2022-10-27 11:22:39 +05:00
this . userRepository = userRepository ;
2022-02-17 15:37:27 +05:00
this . wellService = wellService ;
2022-02-28 14:44:15 +05:00
this . configuration = configuration ;
2022-02-17 15:37:27 +05:00
this . backgroundWorker = backgroundWorker ;
2022-04-25 15:38:44 +05:00
this . emailService = emailService ;
2022-02-17 15:37:27 +05:00
}
public async Task < IEnumerable < UserDto > > GetAvailableUsers ( int idWell , CancellationToken token = default )
{
var users = await context . RelationCompaniesWells
. Include ( r = > r . Company )
. ThenInclude ( c = > c . Users )
. Where ( r = > r . IdWell = = idWell )
. SelectMany ( r = > r . Company . Users )
. Where ( u = > u ! = null & & ! string . IsNullOrEmpty ( u . Email ) )
. ToListAsync ( token ) ;
2022-06-06 15:43:47 +05:00
var usersDto = users . Adapt < IEnumerable < UserDto > > ( ) ;
2022-02-17 15:37:27 +05:00
return usersDto ;
2022-02-12 11:28:16 +05:00
}
public async Task < IEnumerable < FileCategoryDto > > GetCategoriesAsync ( CancellationToken token = default )
{
var result = await context . FileCategories
2022-04-11 18:00:34 +05:00
. Where ( c = > c . Id > idFileCategoryDrillingProgramPartsStart & & c . Id < idFileCategoryDrillingProgramPartsEnd )
2022-02-12 11:28:16 +05:00
. 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 )
2022-04-11 18:00:34 +05:00
. Where ( f = > f . IdWell = = idWell & &
f . IdCategory > = idFileCategoryDrillingProgram & &
2022-02-12 11:28:16 +05:00
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 )
2022-07-06 17:24:09 +05:00
. ThenInclude ( u = > u . Company )
2022-02-12 11:28:16 +05:00
. Where ( p = > p . IdWell = = idWell )
. ToListAsync ( token ) ;
var parts = new List < DrillingProgramPartDto > ( partEntities . Count ) ;
2022-03-02 17:41:59 +05:00
var timezoneOffset = wellService . GetTimezone ( idWell ) ? . Hours ? ? 5 ;
2022-02-12 11:28:16 +05:00
foreach ( var partEntity in partEntities )
{
2022-03-02 17:41:59 +05:00
var part = ConvertPart ( idUser , fileCategories , files , partEntity , timezoneOffset ) ;
2022-02-12 11:28:16 +05:00
parts . Add ( part ) ;
}
2022-02-17 15:37:27 +05:00
var state = new DrillingProgramStateDto
{
Parts = parts ,
Program = files . FirstOrDefault ( f = > f . IdCategory = = idFileCategoryDrillingProgram )
2022-12-02 14:48:23 +05:00
? . Adapt < FileInfoDto > ( ) ,
2022-10-27 11:22:39 +05:00
PermissionToEdit = userRepository . HasPermission ( idUser , "DrillingProgram.edit" ) ,
2022-02-17 15:37:27 +05:00
} ;
2022-02-12 11:28:16 +05:00
if ( parts . Any ( ) )
{
2022-04-11 18:00:34 +05:00
if ( parts . All ( p = > p . IdState = = idPartStateApproved ) )
2022-02-12 11:28:16 +05:00
{
if ( state . Program is not null )
2022-02-28 14:44:15 +05:00
{
2022-02-12 11:28:16 +05:00
state . IdState = idStateReady ;
2022-02-28 14:44:15 +05:00
}
else
{
var workId = MakeWorkId ( idWell ) ;
if ( drillingProgramCreateErrors . ContainsKey ( workId ) )
{
state . IdState = idStateError ;
state . Error = drillingProgramCreateErrors [ workId ] ;
}
else
state . IdState = idStateCreating ;
}
2022-02-12 11:28:16 +05:00
}
else
state . IdState = idStateApproving ;
}
else
state . IdState = idStateNotInitialized ;
2022-12-02 14:48:23 +05:00
await EnqueueMakeProgramWorkAsync ( idWell , state , token ) ;
2022-02-12 11:28:16 +05:00
return state ;
}
2023-01-26 15:25:09 +05:00
private bool ValidExtFile ( string file )
{
var fileExt = Path . GetExtension ( file ) ;
var badExt = Array . Find ( filePermittedExt , e = > e = = fileExt ) ;
if ( badExt is null )
return false ;
return true ;
}
2022-02-18 14:16:35 +05:00
public async Task < int > AddFile ( int idWell , int idFileCategory , int idUser , string fileFullName , System . IO . Stream fileStream , CancellationToken token = default )
2022-02-12 11:28:16 +05:00
{
2023-01-26 15:25:09 +05:00
if ( ! ValidExtFile ( fileFullName ) )
throw new FileFormatException ( $"Файл {fileFullName} - неподдерживаемого формата. Файл не может быть загружен. " ) ;
2022-02-12 11:28:16 +05:00
var part = await context . DrillingProgramParts
2023-01-26 15:25:09 +05:00
. Include ( p = > p . RelatedUsers )
. ThenInclude ( r = > r . User )
. FirstOrDefaultAsync ( p = > p . IdWell = = idWell & & p . IdFileCategory = = idFileCategory , token ) ;
2022-04-11 18:00:34 +05:00
2022-02-12 11:28:16 +05:00
if ( part = = null )
2022-02-18 14:16:35 +05:00
throw new ArgumentInvalidException ( $"DrillingProgramPart id == {idFileCategory} does not exist" , nameof ( idFileCategory ) ) ;
2022-02-12 11:28:16 +05:00
2022-04-11 18:00:34 +05:00
if ( ! part . RelatedUsers . Any ( r = > r . IdUser = = idUser & & r . IdUserRole = = idUserRolePublisher ) )
2022-02-12 11:28:16 +05:00
throw new ForbidException ( $"User {idUser} is not in the publisher list." ) ;
var result = await fileService . SaveAsync (
2022-04-11 18:00:34 +05:00
part . IdWell ,
idUser ,
part . IdFileCategory ,
fileFullName ,
fileStream ,
2022-02-12 11:28:16 +05:00
token ) ;
await RemoveDrillingProgramAsync ( part . IdWell , token ) ;
2022-04-25 15:38:44 +05:00
2022-06-15 14:57:37 +05:00
await NotifyApproversAsync ( part , result . Id , fileFullName , token ) ;
2022-05-04 15:02:12 +05:00
2022-02-12 11:28:16 +05:00
return result . Id ;
}
2022-04-11 18:00:34 +05:00
2022-02-17 15:37:27 +05:00
public async Task < int > AddPartsAsync ( int idWell , IEnumerable < int > idFileCategories , CancellationToken token = default )
2022-02-12 11:28:16 +05:00
{
2022-02-17 15:37:27 +05:00
if ( ! idFileCategories . Any ( ) )
return 0 ;
var existingCategories = await context . DrillingProgramParts
. Where ( p = > p . IdWell = = idWell )
. Select ( p = > p . IdFileCategory )
. ToListAsync ( token ) ;
var newParts = idFileCategories
. Where ( c = > ! existingCategories . Any ( e = > e = = c ) )
. Select ( c = > new DrillingProgramPart
2022-04-11 18:00:34 +05:00
{
IdWell = idWell ,
IdFileCategory = c ,
} ) ;
2022-02-12 11:28:16 +05:00
2022-02-17 15:37:27 +05:00
context . DrillingProgramParts . AddRange ( newParts ) ;
var affected = await context . SaveChangesAsync ( token ) ;
await RemoveDrillingProgramAsync ( idWell , token ) ;
return affected ;
2022-02-12 11:28:16 +05:00
}
2022-02-17 15:37:27 +05:00
public async Task < int > RemovePartsAsync ( int idWell , IEnumerable < int > idFileCategories , CancellationToken token = default )
2022-02-12 11:28:16 +05:00
{
var whereQuery = context . DrillingProgramParts
2022-02-17 15:37:27 +05:00
. Where ( p = > p . IdWell = = idWell & & idFileCategories . Contains ( p . IdFileCategory ) ) ;
2022-02-12 11:28:16 +05:00
context . DrillingProgramParts . RemoveRange ( whereQuery ) ;
await RemoveDrillingProgramAsync ( idWell , token ) ;
return await context . SaveChangesAsync ( token ) ;
}
2022-02-18 14:16:35 +05:00
public async Task < int > AddUserAsync ( int idWell , int idFileCategory , int idUser , int idUserRole , CancellationToken token = default )
2022-02-12 11:28:16 +05:00
{
2022-10-27 11:22:39 +05:00
var user = await userRepository . GetOrDefaultAsync ( idUser , token ) ;
2022-02-12 11:28:16 +05:00
if ( user is null )
throw new ArgumentInvalidException ( $"User id == {idUser} does not exist" , nameof ( idUser ) ) ;
2022-02-18 14:16:35 +05:00
var part = await context . DrillingProgramParts
2022-06-15 14:57:37 +05:00
. Include ( p = > p . FileCategory )
2022-02-18 14:16:35 +05:00
. FirstOrDefaultAsync ( p = > p . IdWell = = idWell & & p . IdFileCategory = = idFileCategory , token ) ;
if ( part is null )
throw new ArgumentInvalidException ( $"DrillingProgramPart idFileCategory == {idFileCategory} does not exist" , nameof ( idFileCategory ) ) ;
2022-02-12 11:28:16 +05:00
if ( idUserRole ! = idUserRoleApprover & & idUserRole ! = idUserRolePublisher )
2022-02-18 14:16:35 +05:00
throw new ArgumentInvalidException ( $"idUserRole ({idUserRole}), should be approver ({idUserRoleApprover}) or publisher ({idUserRolePublisher})" , nameof ( idUserRole ) ) ;
var oldRelation = await context . RelationDrillingProgramPartUsers
. FirstOrDefaultAsync ( r = > r . IdUser = = idUser & & r . IdDrillingProgramPart = = part . Id , token ) ;
2022-04-11 18:00:34 +05:00
if ( oldRelation is not null )
2022-02-18 14:16:35 +05:00
context . RelationDrillingProgramPartUsers . Remove ( oldRelation ) ;
2022-02-12 11:28:16 +05:00
var newRelation = new RelationUserDrillingProgramPart
{
IdUser = idUser ,
2022-02-18 14:16:35 +05:00
IdDrillingProgramPart = part . Id ,
2022-02-12 11:28:16 +05:00
IdUserRole = idUserRole ,
} ;
context . RelationDrillingProgramPartUsers . Add ( newRelation ) ;
2022-04-11 18:00:34 +05:00
if ( idUserRole = = idUserRoleApprover )
2022-02-18 14:16:35 +05:00
await RemoveDrillingProgramAsync ( part . IdWell , token ) ;
2022-05-04 15:02:12 +05:00
2022-05-18 11:07:39 +05:00
if ( idUserRole = = idUserRolePublisher )
await NotifyNewPublisherAsync ( idWell , user , part . FileCategory . Name , token ) ;
2022-05-04 15:02:12 +05:00
2022-02-12 11:28:16 +05:00
return await context . SaveChangesAsync ( token ) ;
}
2022-02-18 14:16:35 +05:00
public async Task < int > RemoveUserAsync ( int idWell , int idFileCategory , int idUser , int idUserRole , CancellationToken token = default )
2022-02-12 11:28:16 +05:00
{
var whereQuery = context . RelationDrillingProgramPartUsers
2022-02-18 14:16:35 +05:00
. Include ( r = > r . DrillingProgramPart )
2022-02-12 11:28:16 +05:00
. Where ( r = > r . IdUser = = idUser & &
2022-02-18 14:16:35 +05:00
r . IdUserRole = = idUserRole & &
r . DrillingProgramPart . IdWell = = idWell & &
r . DrillingProgramPart . IdFileCategory = = idFileCategory ) ;
2022-02-12 11:28:16 +05:00
context . RelationDrillingProgramPartUsers . RemoveRange ( whereQuery ) ;
2022-04-11 18:00:34 +05:00
2022-02-12 11:28:16 +05:00
return await context . SaveChangesAsync ( token ) ;
}
public async Task < int > AddOrReplaceFileMarkAsync ( FileMarkDto fileMarkDto , int idUser , CancellationToken token )
{
2022-04-11 18:00:34 +05:00
if ( fileMarkDto . IdMarkType ! = idMarkTypeApprove & &
2022-02-12 11:28:16 +05:00
fileMarkDto . IdMarkType ! = idMarkTypeReject )
throw new ArgumentInvalidException ( $"В этом методе допустимы только отметки о принятии или отклонении." , nameof ( fileMarkDto ) ) ;
2022-10-17 14:42:47 +05:00
var fileInfo = await fileService . GetOrDefaultAsync ( fileMarkDto . IdFile , token )
2022-02-12 11:28:16 +05:00
. 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
2022-02-17 15:37:27 +05:00
. Include ( p = > p . RelatedUsers )
2022-05-18 11:07:39 +05:00
. ThenInclude ( r = > r . User )
. AsNoTracking ( )
2022-02-12 11:28:16 +05:00
. FirstOrDefaultAsync ( p = > p . IdWell = = fileInfo . IdWell & & p . IdFileCategory = = fileInfo . IdCategory , token ) ;
2022-12-02 14:48:23 +05:00
var user = part ? . RelatedUsers . FirstOrDefault ( r = > r . IdUser = = idUser & & r . IdUserRole = = idUserRoleApprover ) ? . User ;
2022-05-18 11:07:39 +05:00
if ( user is null )
2022-02-12 11:28:16 +05:00
throw new ForbidException ( $"User {idUser} is not in the approvers list." ) ;
2022-05-18 11:07:39 +05:00
fileMarkDto . User = user . Adapt < UserDto > ( ) ;
2022-02-12 11:28:16 +05:00
var oldMarksIds = fileInfo . FileMarks
? . Where ( m = > m . User . Id = = idUser )
. Select ( m = > m . Id ) ;
2022-04-11 18:00:34 +05:00
if ( oldMarksIds ? . Any ( ) = = true )
2022-09-30 13:34:50 +05:00
await fileService . MarkFileMarkAsDeletedAsync ( oldMarksIds , token ) ;
2022-02-12 11:28:16 +05:00
2022-09-30 13:34:50 +05:00
var result = await fileService . CreateFileMarkAsync ( fileMarkDto , idUser , token )
2022-02-12 11:28:16 +05:00
. ConfigureAwait ( false ) ;
2022-04-11 18:00:34 +05:00
if ( fileMarkDto . IdMarkType = = idMarkTypeReject )
2022-04-25 15:38:44 +05:00
{
2022-02-12 11:28:16 +05:00
await RemoveDrillingProgramAsync ( fileInfo . IdWell , token ) ;
2022-05-04 15:02:12 +05:00
await NotifyPublisherOnRejectAsync ( fileMarkDto , token ) ;
2022-04-25 15:38:44 +05:00
}
2022-05-18 11:07:39 +05:00
else
2022-04-25 15:38:44 +05:00
{
2022-05-18 11:07:39 +05:00
// если все согласованты согласовали - оповещаем публикатора
2022-12-02 14:48:23 +05:00
var approvers = part ! . RelatedUsers
2022-05-18 11:07:39 +05:00
. Where ( u = > u . IdUserRole = = idUserRoleApprover ) ;
if ( approvers
. All ( user = > fileInfo . FileMarks
2022-12-02 14:48:23 +05:00
? . Any ( mark = > ( mark . IdMarkType = = idMarkTypeApprove & & mark . User . Id = = user . IdUser & & ! mark . IsDeleted ) ) = = true | |
2022-05-18 11:07:39 +05:00
( fileMarkDto . IdMarkType = = idMarkTypeApprove & & user . IdUser = = idUser ) ) )
{
await NotifyPublisherOnFullAccepAsync ( fileMarkDto , token ) ;
}
2022-04-25 15:38:44 +05:00
}
2022-05-18 11:07:39 +05:00
2022-02-12 11:28:16 +05:00
return result ;
}
public async Task < int > MarkAsDeletedFileMarkAsync ( int idMark ,
CancellationToken token )
{
2022-09-30 13:34:50 +05:00
var fileInfo = await fileService . GetByMarkId ( idMark , token )
2022-02-12 11:28:16 +05:00
. 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 ;
}
2022-05-04 15:02:12 +05:00
private async Task NotifyPublisherOnFullAccepAsync ( FileMarkDto fileMark , CancellationToken token )
{
2022-10-17 14:42:47 +05:00
var file = await fileService . GetOrDefaultAsync ( fileMark . IdFile , token ) ;
2022-12-02 14:48:23 +05:00
var well = await wellService . GetOrDefaultAsync ( file ! . IdWell , token ) ;
2022-05-04 15:02:12 +05:00
var user = file . Author ;
2022-09-08 12:05:56 +05:00
var factory = new DrillingMailBodyFactory ( configuration ) ;
var subject = factory . MakeSubject ( well , "Загруженный вами документ полностью согласован" ) ;
2022-05-04 15:02:12 +05:00
var body = factory . MakeMailBodyForPublisherOnFullAccept ( well , user . Name , file . Id , file . Name ) ;
emailService . EnqueueSend ( user . Email , subject , body ) ;
}
private async Task NotifyPublisherOnRejectAsync ( FileMarkDto fileMark , CancellationToken token )
{
2022-10-17 14:42:47 +05:00
var file = await fileService . GetOrDefaultAsync ( fileMark . IdFile , token ) ;
2022-12-02 14:48:23 +05:00
var well = await wellService . GetOrDefaultAsync ( file ! . IdWell , token ) ;
2022-05-04 15:02:12 +05:00
var user = file . Author ;
2022-09-08 12:05:56 +05:00
var factory = new DrillingMailBodyFactory ( configuration ) ;
var subject = factory . MakeSubject ( well , "Загруженный вами документ отклонен" ) ;
2022-05-04 15:02:12 +05:00
var body = factory . MakeMailBodyForPublisherOnReject ( well , user . Name , file . Id , file . Name , fileMark ) ;
emailService . EnqueueSend ( user . Email , subject , body ) ;
}
private async Task NotifyApproversAsync ( DrillingProgramPart part , int idFile , string fileName , CancellationToken token )
{
2022-06-16 12:33:05 +05:00
var well = await wellService . GetOrDefaultAsync ( part . IdWell , token ) ;
2022-09-08 12:05:56 +05:00
var factory = new DrillingMailBodyFactory ( configuration ) ;
var subject = factory . MakeSubject ( well , "Загружен новый документ для согласования." ) ;
2022-05-04 15:02:12 +05:00
var users = part . RelatedUsers
. Where ( r = > r . IdUserRole = = idUserRoleApprover )
. Select ( r = > r . User ) ;
foreach ( var user in users )
{
var body = factory . MakeMailBodyForApproverNewFile ( well , user . Name , idFile , fileName ) ;
emailService . EnqueueSend ( user . Email , subject , body ) ;
}
}
private async Task NotifyNewPublisherAsync ( int idWell , UserDto user , string documentCategory , CancellationToken token )
{
2022-06-16 12:33:05 +05:00
var well = await wellService . GetOrDefaultAsync ( idWell , token ) ;
2022-09-08 12:05:56 +05:00
var factory = new DrillingMailBodyFactory ( configuration ) ;
var subject = factory . MakeSubject ( well , $"От вас ожидается загрузка на портал документа «{documentCategory}»" ) ;
2022-05-04 15:02:12 +05:00
var body = factory . MakeMailBodyForNewPublisher ( well , user . Name , documentCategory ) ;
emailService . EnqueueSend ( user . Email , subject , body ) ;
}
2022-12-02 14:48:23 +05:00
private static DrillingProgramPartDto ConvertPart ( int idUser , List < FileCategory > fileCategories , List < AsbCloudDb . Model . FileInfo > files , DrillingProgramPart partEntity , double timezoneOffset )
2022-02-12 11:28:16 +05:00
{
var part = new DrillingProgramPartDto
{
IdFileCategory = partEntity . IdFileCategory ,
2022-12-02 14:48:23 +05:00
Name = fileCategories . FirstOrDefault ( c = > c . Id = = partEntity . IdFileCategory ) ! . Name ,
2022-02-12 11:28:16 +05:00
Approvers = partEntity . RelatedUsers
2022-02-17 15:37:27 +05:00
. Where ( r = > r . IdUserRole = = idUserRoleApprover )
. Select ( r = > r . User . Adapt < UserDto > ( ) ) ,
2022-02-12 11:28:16 +05:00
Publishers = partEntity . RelatedUsers
2022-02-17 15:37:27 +05:00
. Where ( r = > r . IdUserRole = = idUserRolePublisher )
. Select ( r = > r . User . Adapt < UserDto > ( ) ) ,
2022-02-12 11:28:16 +05:00
PermissionToApprove = partEntity . RelatedUsers
2022-02-17 15:37:27 +05:00
. Any ( r = > r . IdUserRole = = idUserRoleApprover & & r . IdUser = = idUser ) ,
2022-02-12 11:28:16 +05:00
PermissionToUpload = partEntity . RelatedUsers
2022-02-17 15:37:27 +05:00
. Any ( r = > r . IdUserRole = = idUserRolePublisher & & r . IdUser = = idUser ) ,
2022-02-12 11:28:16 +05:00
} ;
var fileEntity = files . LastOrDefault ( f = > f . IdCategory = = partEntity . IdFileCategory ) ;
if ( fileEntity is not null )
{
2022-02-17 15:37:27 +05:00
part . IdState = idPartStateApproving ;
2022-03-02 17:41:59 +05:00
part . File = new FileInfoDto
2022-02-12 11:28:16 +05:00
{
2022-03-02 17:41:59 +05:00
Id = fileEntity . Id ,
Author = fileEntity . Author . Adapt < UserDto > ( ) ,
IdAuthor = fileEntity . Author . Id ,
IdCategory = fileEntity . IdCategory ,
IdWell = fileEntity . IdWell ,
Name = fileEntity . Name ,
Size = fileEntity . Size ,
UploadDate = fileEntity . UploadDate . ToRemoteDateTime ( timezoneOffset ) ,
} ;
var marks = fileEntity . FileMarks ? . Where ( m = > ! m . IsDeleted ) ;
if ( marks ? . Any ( ) = = true )
2022-04-11 18:00:34 +05:00
{
part . File . FileMarks = marks . Select ( m = >
{
2022-03-02 17:41:59 +05:00
var mark = m . Adapt < FileMarkDto > ( ) ;
mark . DateCreated = m . DateCreated . ToRemoteDateTime ( timezoneOffset ) ;
return mark ;
} ) ;
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 ;
}
2022-02-12 11:28:16 +05:00
}
}
else
part . IdState = idPartStateNoFile ;
return part ;
}
2023-01-26 15:25:09 +05:00
2022-12-02 14:48:23 +05:00
private async Task EnqueueMakeProgramWorkAsync ( int idWell , DrillingProgramStateDto state , CancellationToken token )
2022-02-12 11:28:16 +05:00
{
2022-02-17 15:37:27 +05:00
if ( state . IdState = = idStateCreating )
2022-02-12 11:28:16 +05:00
{
2022-02-17 15:37:27 +05:00
var workId = MakeWorkId ( idWell ) ;
if ( ! backgroundWorker . Contains ( workId ) )
{
2022-12-02 14:48:23 +05:00
var well = ( await wellService . GetOrDefaultAsync ( idWell , token ) ) ! ;
2023-01-25 05:32:32 +05:00
var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.pdf" ;
var convertedFilesDir = Path . Combine ( Path . GetTempPath ( ) , "drillingProgram" , $"{well.Cluster}_{well.Caption}" ) ;
var tempResultFilePath = Path . Combine ( convertedFilesDir , resultFileName ) ;
2022-12-02 14:48:23 +05:00
var workAction = async ( string workId , IServiceProvider serviceProvider , CancellationToken token ) = >
2022-02-17 15:37:27 +05:00
{
2022-12-02 14:48:23 +05:00
var context = serviceProvider . GetRequiredService < IAsbCloudDbContext > ( ) ;
var fileService = serviceProvider . GetRequiredService < FileService > ( ) ;
2023-01-13 17:28:04 +05:00
var files = state . Parts . Select ( p = > fileService . GetUrl ( p . File ) ) ;
2023-01-25 05:32:32 +05:00
await ConvertToPdf . GetConverteAndMergedFileAsync ( files , tempResultFilePath , convertedFilesDir , token ) ;
2022-02-17 15:37:27 +05:00
await fileService . MoveAsync ( idWell , null , idFileCategoryDrillingProgram , resultFileName , tempResultFilePath , token ) ;
2022-12-02 14:48:23 +05:00
} ;
2022-02-17 15:37:27 +05:00
2022-12-02 14:48:23 +05:00
var onErrorAction = ( string workId , Exception exception , CancellationToken token ) = >
2022-04-11 18:00:34 +05:00
{
2022-02-28 14:44:15 +05:00
var message = $"Н е удалось сформировать программу бурения по скважине {well?.Caption}" ;
2022-04-11 18:00:34 +05:00
drillingProgramCreateErrors [ workId ] = new ( )
{
2022-02-28 14:44:15 +05:00
Message = message ,
Exception = exception . Message ,
} ;
return Task . CompletedTask ;
2022-12-02 14:48:23 +05:00
} ;
var work = new WorkBase ( workId , workAction )
{
ExecutionTime = TimeSpan . FromMinutes ( 1 ) ,
OnErrorAsync = onErrorAction
} ;
2022-02-28 14:44:15 +05:00
2022-12-02 14:48:23 +05:00
backgroundWorker . Push ( work ) ;
2022-02-17 15:37:27 +05:00
}
2022-02-12 11:28:16 +05:00
}
}
2022-02-28 14:44:15 +05:00
public void ClearError ( int idWell )
{
var workId = MakeWorkId ( idWell ) ;
drillingProgramCreateErrors . Remove ( workId ) ;
}
2022-02-12 11:28:16 +05:00
private async Task < int > RemoveDrillingProgramAsync ( int idWell , CancellationToken token )
{
2022-02-17 15:37:27 +05:00
var workId = MakeWorkId ( idWell ) ;
2022-12-02 14:48:23 +05:00
backgroundWorker . Delete ( workId ) ;
2022-02-17 15:37:27 +05:00
2022-02-12 11:28:16 +05:00
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 ;
}
2022-04-11 18:00:34 +05:00
private static string MakeWorkId ( int idWell )
2022-02-17 15:37:27 +05:00
= > $"Make drilling program for wellId {idWell}" ;
2022-02-12 11:28:16 +05:00
}
2022-12-02 14:48:23 +05:00
#nullable disable
2022-02-12 11:28:16 +05:00
}