diff --git a/Sheaft.Application.Commands/Producer/GenerateProducersFileCommand.cs b/Sheaft.Application.Commands/Producer/GenerateProducersFileCommand.cs new file mode 100644 index 000000000..2f26e1db3 --- /dev/null +++ b/Sheaft.Application.Commands/Producer/GenerateProducersFileCommand.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; +using Sheaft.Core; + +namespace Sheaft.Application.Commands +{ + public class GenerateProducersFileCommand : Command + { + [JsonConstructor] + public GenerateProducersFileCommand(RequestUser requestUser) : base(requestUser) + { + } + } +} diff --git a/Sheaft.Application.Handlers/Commands/ProducerCommandsHandler.cs b/Sheaft.Application.Handlers/Commands/ProducerCommandsHandler.cs index fb630b6cd..d758014f7 100644 --- a/Sheaft.Application.Handlers/Commands/ProducerCommandsHandler.cs +++ b/Sheaft.Application.Handlers/Commands/ProducerCommandsHandler.cs @@ -14,10 +14,14 @@ using Sheaft.Exceptions; using Microsoft.EntityFrameworkCore; using Sheaft.Application.Events; +using Newtonsoft.Json; +using System.Text; +using Newtonsoft.Json.Serialization; namespace Sheaft.Application.Handlers { public class ProducerCommandsHandler : ResultsHandler, + IRequestHandler>, IRequestHandler>, IRequestHandler>, IRequestHandler>, @@ -25,15 +29,36 @@ public class ProducerCommandsHandler : ResultsHandler, IRequestHandler> { private readonly RoleOptions _roleOptions; + private readonly IBlobService _blobService; public ProducerCommandsHandler( IAppDbContext context, ISheaftMediatr mediatr, + IBlobService blobService, ILogger logger, IOptionsSnapshot roleOptions) : base(mediatr, context, logger) { _roleOptions = roleOptions.Value; + _blobService = blobService; + } + + public async Task> Handle(GenerateProducersFileCommand request, CancellationToken token) + { + return await ExecuteAsync(request, async () => + { + var producers = await _context.GetAsync(token); + var prods = producers.Select(p => new ProducerListItem(p)); + + var result = await _blobService.UploadProducersListAsync( + Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(prods, + new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() }})), token); + + if(!result.Success) + return Failed(result.Exception); + + return Ok(true); + }); } public async Task> Handle(RegisterProducerCommand request, CancellationToken token) @@ -233,6 +258,39 @@ public async Task> Handle(SetProducerProductsWithNoVatCommand reque return Ok(true); }); + } + + internal class ProducerListItem + { + internal ProducerListItem(User user) + { + Address = new AddressItem(user.Address); + Id = user.Id.ToString("N"); + Name = user.Name; + Picture = user.Picture; + } + public string Id { get; set; } + public string Name { get; set; } + public string Picture { get; set; } + public AddressItem Address { get; set; } + } + + internal class AddressItem { + internal AddressItem(UserAddress address) + { + Line1 = address.Line1; + Line2 = address.Line2; + Zipcode = address.Zipcode; + City = address.City; + Latitude = address.Latitude; + Longitude = address.Longitude; + } + public string Line1 { get; set; } + public string Line2 { get; set; } + public string Zipcode { get; set; } + public string City { get; set; } + public double? Latitude { get; set; } + public double? Longitude { get; set; } } } } \ No newline at end of file diff --git a/Sheaft.Application.Interop/Persistence/IAppDbContext.cs b/Sheaft.Application.Interop/Persistence/IAppDbContext.cs index dfd20912a..4ff85bf4f 100644 --- a/Sheaft.Application.Interop/Persistence/IAppDbContext.cs +++ b/Sheaft.Application.Interop/Persistence/IAppDbContext.cs @@ -60,8 +60,11 @@ public interface IAppDbContext : IDisposable, IAsyncDisposable, IInfrastructure< Task> GetByIdsAsync(IEnumerable ids, CancellationToken token, bool asNoTracking = false) where T : class, IIdEntity, ITrackRemove; Task> FindByIdsAsync(IEnumerable ids, CancellationToken token, bool asNoTracking = false) where T : class, IIdEntity, ITrackRemove; Task> GetAsync(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove; + Task> GetAsync(CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove; Task> FindAsync(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove; + Task> FindAsync(CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove; Task AnyAsync(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove; + Task AnyAsync(CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove; Task EnsureNotExists(Guid id, CancellationToken token, bool asNoTracking = false) where T : class, IIdEntity, ITrackRemove; Task EnsureNotExists(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, IIdEntity, ITrackRemove; diff --git a/Sheaft.Application.Interop/Services/IBlobsService.cs b/Sheaft.Application.Interop/Services/IBlobsService.cs index 79cf2f5dd..64e9df2e9 100644 --- a/Sheaft.Application.Interop/Services/IBlobsService.cs +++ b/Sheaft.Application.Interop/Services/IBlobsService.cs @@ -21,5 +21,6 @@ public interface IBlobService Task> DownloadDocumentPageAsync(Guid documentId, Guid pageId, Guid userId, CancellationToken token); Task> UploadDocumentPageAsync(Guid documentId, Guid pageId, byte[] data, Guid userId, CancellationToken token); Task> DeleteDocumentPageAsync(Guid documentId, Guid pageId, Guid userId, CancellationToken token); + Task> UploadProducersListAsync(byte[] data, CancellationToken token); } } \ No newline at end of file diff --git a/Sheaft.Infrastructure.Persistence/AppDbContext.cs b/Sheaft.Infrastructure.Persistence/AppDbContext.cs index 498d46111..e785ae78d 100644 --- a/Sheaft.Infrastructure.Persistence/AppDbContext.cs +++ b/Sheaft.Infrastructure.Persistence/AppDbContext.cs @@ -132,7 +132,10 @@ public async Task> FindByIdsAsync(IEnumerable ids, Cance public async Task> GetAsync(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove { - var query = Set().Where(c => !c.RemovedOn.HasValue).Where(where); + var query = Set().Where(c => !c.RemovedOn.HasValue); + if(where != null) + query = query.Where(where); + if (asNoTracking) query = query.AsNoTracking(); @@ -146,9 +149,17 @@ public async Task> GetAsync(Expression> where, C return items; } + public async Task> GetAsync(CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove + { + return await GetAsync(null, token, asNoTracking); + } + public async Task> FindAsync(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove { - var query = Set().Where(c => !c.RemovedOn.HasValue).Where(where); + var query = Set().Where(c => !c.RemovedOn.HasValue); + if(where != null) + query = query.Where(where); + if (asNoTracking) query = query.AsNoTracking(); @@ -159,9 +170,17 @@ public async Task> FindAsync(Expression> where, return items; } + public async Task> FindAsync(CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove + { + return await FindAsync(null, token, asNoTracking); + } + public async Task GetSingleAsync(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove { - var query = Set().Where(c => !c.RemovedOn.HasValue).Where(where); + var query = Set().Where(c => !c.RemovedOn.HasValue); + if(where != null) + query = query.Where(where); + if (asNoTracking) query = query.AsNoTracking(); @@ -177,7 +196,10 @@ public async Task GetSingleAsync(Expression> where, Cancella public async Task FindSingleAsync(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove { - var query = Set().Where(c => !c.RemovedOn.HasValue).Where(where); + var query = Set().Where(c => !c.RemovedOn.HasValue); + if(where != null) + query = query.Where(where); + if (asNoTracking) query = query.AsNoTracking(); @@ -186,13 +208,21 @@ public async Task FindSingleAsync(Expression> where, Cancell public async Task AnyAsync(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove { - var query = Set().Where(c => !c.RemovedOn.HasValue).Where(where); + var query = Set().Where(c => !c.RemovedOn.HasValue); + if(where != null) + query = query.Where(where); + if (asNoTracking) query = query.AsNoTracking(); return await query.AnyAsync(token); } + public async Task AnyAsync(CancellationToken token, bool asNoTracking = false) where T : class, ITrackRemove + { + return await AnyAsync(null, token, asNoTracking); + } + public async Task EnsureNotExists(Guid id, CancellationToken token, bool asNoTracking = false) where T : class, IIdEntity, ITrackRemove { var query = Set().Where(c => !c.RemovedOn.HasValue && c.Id == id); @@ -209,7 +239,10 @@ public async Task EnsureNotExists(Guid id, CancellationToken token, bool asNo public async Task EnsureNotExists(Expression> where, CancellationToken token, bool asNoTracking = false) where T : class, IIdEntity, ITrackRemove { - var query = Set().Where(c => !c.RemovedOn.HasValue).Where(where); + var query = Set().Where(c => !c.RemovedOn.HasValue); + if(where != null) + query = query.Where(where); + if (asNoTracking) query = query.AsNoTracking(); diff --git a/Sheaft.Infrastructure.Services/BlobService.cs b/Sheaft.Infrastructure.Services/BlobService.cs index 088f4c4a5..8939bf50b 100644 --- a/Sheaft.Infrastructure.Services/BlobService.cs +++ b/Sheaft.Infrastructure.Services/BlobService.cs @@ -295,6 +295,23 @@ public async Task> UploadDepartmentsProgressAsync(byte[] data, Ca }); } + public async Task> UploadProducersListAsync(byte[] data, CancellationToken token) + { + return await ExecuteAsync(async () => + { + var containerClient = new BlobContainerClient(_storageOptions.ConnectionString, _storageOptions.Containers.Producers); + await containerClient.CreateIfNotExistsAsync(cancellationToken: token); + + var blobClient = containerClient.GetBlobClient("producers.json"); + await blobClient.DeleteIfExistsAsync(cancellationToken: token); + + using (var ms = new MemoryStream(data)) + await blobClient.UploadAsync(ms, token); + + return Ok(blobClient.Uri.ToString()); + }); + } + private string GetBlobSasUri(BlobClient blobClient, BlobSasBuilder sasBuilder, string container) { return new UriBuilder diff --git a/Sheaft.Options/RoutineOptions.cs b/Sheaft.Options/RoutineOptions.cs index 1db4c8169..e436f8f5e 100644 --- a/Sheaft.Options/RoutineOptions.cs +++ b/Sheaft.Options/RoutineOptions.cs @@ -9,6 +9,7 @@ public class RoutineOptions public string CheckPayinsCron { get; set; } = "*/30 * * * *"; public string CheckZonesProgressCron { get; set; } = "0 0 * * *"; public string CheckZonesFileCron { get; set; } = "30 0 * * *"; + public string CheckProducersFileCron { get; set; } = "45 0 * * *"; public string CheckOrdersCron { get; set; } = "0 1 * * *"; public string CheckTransfersCron { get; set; } = "0 2 * * *"; public string CheckPayoutsCron { get; set; } = "0 3 * * *"; diff --git a/Sheaft.Options/StorageOptions.cs b/Sheaft.Options/StorageOptions.cs index e6e76d96f..5db5c3778 100644 --- a/Sheaft.Options/StorageOptions.cs +++ b/Sheaft.Options/StorageOptions.cs @@ -25,6 +25,7 @@ public class StorageContainers public string Rgpd { get; set; } = "rgpd"; public string PickingOrders { get; set; } = "pickingorders"; public string Progress { get; set; } = "progress"; + public string Producers { get; set; } = "producers"; public string Documents { get; set; } = "documents"; } public class StorageTables diff --git a/Sheaft.Web.Jobs/Startup.cs b/Sheaft.Web.Jobs/Startup.cs index 339f0c71f..51094befe 100644 --- a/Sheaft.Web.Jobs/Startup.cs +++ b/Sheaft.Web.Jobs/Startup.cs @@ -332,40 +332,44 @@ public static class RecuringJobs public static void Register(RoutineOptions options) { RecurringJob.AddOrUpdate("79d5e199b5ef41268fade4da1fa3f83b", mediatr => - mediatr.Execute(nameof(CheckOrdersCommand), new CheckOrdersCommand(new RequestUser("79d5e199b5ef41268fade4da1fa3f83b", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + mediatr.Execute(nameof(CheckOrdersCommand), new CheckOrdersCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), options.CheckOrdersCron); RecurringJob.AddOrUpdate("44d0d009c3d24cb6b05f113e49b60d35", mediatr => - mediatr.Execute(nameof(CheckDonationsCommand), new CheckDonationsCommand(new RequestUser("44d0d009c3d24cb6b05f113e49b60d35", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + mediatr.Execute(nameof(CheckDonationsCommand), new CheckDonationsCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), options.CheckDonationsCron); RecurringJob.AddOrUpdate("cd2bc132393f4a379f7ac44d56f84d9e", mediatr => - mediatr.Execute(nameof(CheckPayinsCommand), new CheckPayinsCommand(new RequestUser("cd2bc132393f4a379f7ac44d56f84d9e", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + mediatr.Execute(nameof(CheckPayinsCommand), new CheckPayinsCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), options.CheckPayinsCron); RecurringJob.AddOrUpdate("eaf648de5fe54fc1980c093fd78bb2f7", mediatr => - mediatr.Execute(nameof(CheckPayinRefundsCommand), new CheckPayinRefundsCommand(new RequestUser("eaf648de5fe54fc1980c093fd78bb2f7", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + mediatr.Execute(nameof(CheckPayinRefundsCommand), new CheckPayinRefundsCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), options.CheckPayinRefundsCron); RecurringJob.AddOrUpdate("dddd91a8fa494da3af1477d1b537fd95", mediatr => - mediatr.Execute(nameof(CheckPayoutsCommand), new CheckPayoutsCommand(new RequestUser("dddd91a8fa494da3af1477d1b537fd95", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + mediatr.Execute(nameof(CheckPayoutsCommand), new CheckPayoutsCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), options.CheckPayoutsCron); RecurringJob.AddOrUpdate("50a160aac50f480a872b04a509ef202c", mediatr => - mediatr.Execute(nameof(CheckTransfersCommand), new CheckTransfersCommand(new RequestUser("50a160aac50f480a872b04a509ef202c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + mediatr.Execute(nameof(CheckTransfersCommand), new CheckTransfersCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), options.CheckTransfersCron); RecurringJob.AddOrUpdate("ae81c9c623f940b386ac9d3144147557", mediatr => - mediatr.Execute(nameof(CheckNewPayoutsCommand), new CheckNewPayoutsCommand(new RequestUser("ae81c9c623f940b386ac9d3144147557", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + mediatr.Execute(nameof(CheckNewPayoutsCommand), new CheckNewPayoutsCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), options.CheckNewPayoutsCron); RecurringJob.AddOrUpdate("0b74e15ec9de4332981a8f933377fc0a", mediatr => - mediatr.Execute(nameof(UpdateZonesProgressCommand), new UpdateZonesProgressCommand(new RequestUser("0b74e15ec9de4332981a8f933377fc0a", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + mediatr.Execute(nameof(UpdateZonesProgressCommand), new UpdateZonesProgressCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), options.CheckZonesProgressCron); RecurringJob.AddOrUpdate("7236b37addc04f62ac2afef157903132", mediatr => - mediatr.Execute(nameof(GenerateZonesFileCommand), new GenerateZonesFileCommand(new RequestUser("7236b37addc04f62ac2afef157903132", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + mediatr.Execute(nameof(GenerateZonesFileCommand), new GenerateZonesFileCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), options.CheckZonesFileCron); + + RecurringJob.AddOrUpdate("4787cf27f6bd491292014902a84a11ae", mediatr => + mediatr.Execute(nameof(GenerateProducersFileCommand), new GenerateProducersFileCommand(new RequestUser("037e7e93c73f4406a4e31994d8686b7c", Guid.NewGuid().ToString("N"), null)), CancellationToken.None), + options.CheckProducersFileCron); } } }