-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from neozhu/feature/csvexportimport
Import and Export Features for Products
- Loading branch information
Showing
23 changed files
with
508 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
src/CleanAspire.Application/Features/Products/Commands/ImportProductsCommand.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System.Globalization; | ||
using CleanAspire.Application.Features.Products.DTOs; | ||
using CleanAspire.Application.Features.Products.EventHandlers; | ||
using CleanAspire.Application.Pipeline; | ||
using CsvHelper; | ||
|
||
namespace CleanAspire.Application.Features.Products.Commands; | ||
public record ImportProductsCommand(Stream Stream | ||
) : IFusionCacheRefreshRequest<Unit>, IRequiresValidation | ||
{ | ||
public IEnumerable<string>? Tags => new[] { "products" }; | ||
} | ||
|
||
public class ImportProductsCommandHandler : IRequestHandler<ImportProductsCommand, Unit> | ||
{ | ||
private readonly IApplicationDbContext _context; | ||
|
||
public ImportProductsCommandHandler(IApplicationDbContext context) | ||
{ | ||
_context = context; | ||
} | ||
|
||
public async ValueTask<Unit> Handle(ImportProductsCommand request, CancellationToken cancellationToken) | ||
{ | ||
request.Stream.Position = 0; | ||
using (var reader = new StreamReader(request.Stream)) | ||
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) | ||
{ | ||
var records = csv.GetRecords<ProductDto>(); | ||
foreach (var product in records.Select(x=>new Product() | ||
{ | ||
SKU = x.SKU, | ||
Name = x.Name, | ||
Category = (ProductCategory)x.Category, | ||
Description = x.Description, | ||
Price = x.Price, | ||
Currency = x.Currency, | ||
UOM = x.UOM | ||
})) | ||
{ | ||
product.AddDomainEvent(new ProductCreatedEvent(product)); | ||
_context.Products.Add(product); | ||
} | ||
await _context.SaveChangesAsync(cancellationToken); | ||
} | ||
return Unit.Value; | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
src/CleanAspire.Application/Features/Products/Queries/ExportProductsQuery.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using System.Globalization; | ||
using CleanAspire.Application.Features.Products.DTOs; | ||
using CsvHelper; | ||
|
||
namespace CleanAspire.Application.Features.Products.Queries; | ||
public record ExportProductsQuery(string Keywords) : IRequest<Stream>; | ||
|
||
|
||
public class ExportProductsQueryHandler : IRequestHandler<ExportProductsQuery, Stream> | ||
{ | ||
private readonly IApplicationDbContext _context; | ||
|
||
public ExportProductsQueryHandler(IApplicationDbContext context) | ||
{ | ||
_context = context; | ||
} | ||
|
||
public async ValueTask<Stream> Handle(ExportProductsQuery request, CancellationToken cancellationToken) | ||
{ | ||
var data = await _context.Products.Where(x => x.SKU.Contains(request.Keywords) || x.Name.Contains(request.Keywords) || x.Description.Contains(request.Keywords)) | ||
.Select(t => new ProductDto | ||
{ | ||
Id = t.Id, | ||
Name = t.Name, | ||
Description = t.Description, | ||
Price = t.Price, | ||
SKU = t.SKU, | ||
UOM = t.UOM, | ||
Currency = t.Currency, | ||
Category = (ProductCategoryDto?)t.Category | ||
}).ToListAsync(cancellationToken); | ||
var steam = new MemoryStream(); | ||
using (var writer = new StreamWriter(steam, leaveOpen: true)) | ||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) | ||
{ | ||
csv.WriteRecords(data); | ||
await writer.FlushAsync(); | ||
} | ||
return steam; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
src/CleanAspire.ClientApp/Client/Products/Export/ExportRequestBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// <auto-generated/> | ||
#pragma warning disable CS0618 | ||
using CleanAspire.Api.Client.Models; | ||
using Microsoft.Kiota.Abstractions.Extensions; | ||
using Microsoft.Kiota.Abstractions.Serialization; | ||
using Microsoft.Kiota.Abstractions; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Threading.Tasks; | ||
using System.Threading; | ||
using System; | ||
namespace CleanAspire.Api.Client.Products.Export | ||
{ | ||
/// <summary> | ||
/// Builds and executes requests for operations under \products\export | ||
/// </summary> | ||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] | ||
public partial class ExportRequestBuilder : BaseRequestBuilder | ||
{ | ||
/// <summary> | ||
/// Instantiates a new <see cref="global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder"/> and sets the default values. | ||
/// </summary> | ||
/// <param name="pathParameters">Path parameters for the request</param> | ||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param> | ||
public ExportRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/products/export?keywords={keywords}", pathParameters) | ||
{ | ||
} | ||
/// <summary> | ||
/// Instantiates a new <see cref="global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder"/> and sets the default values. | ||
/// </summary> | ||
/// <param name="rawUrl">The raw URL to use for the request builder.</param> | ||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param> | ||
public ExportRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/products/export?keywords={keywords}", rawUrl) | ||
{ | ||
} | ||
/// <summary> | ||
/// Exports the product data to a CSV file based on the provided keywords. The CSV file includes product details such as ID, name, description, price, SKU, and category. | ||
/// </summary> | ||
/// <returns>A <see cref="Stream"/></returns> | ||
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param> | ||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param> | ||
/// <exception cref="global::CleanAspire.Api.Client.Models.ProblemDetails">When receiving a 500 status code</exception> | ||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER | ||
#nullable enable | ||
public async Task<Stream?> GetAsync(Action<RequestConfiguration<global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder.ExportRequestBuilderGetQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default) | ||
{ | ||
#nullable restore | ||
#else | ||
public async Task<Stream> GetAsync(Action<RequestConfiguration<global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder.ExportRequestBuilderGetQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default) | ||
{ | ||
#endif | ||
var requestInfo = ToGetRequestInformation(requestConfiguration); | ||
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>> | ||
{ | ||
{ "500", global::CleanAspire.Api.Client.Models.ProblemDetails.CreateFromDiscriminatorValue }, | ||
}; | ||
return await RequestAdapter.SendPrimitiveAsync<Stream>(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); | ||
} | ||
/// <summary> | ||
/// Exports the product data to a CSV file based on the provided keywords. The CSV file includes product details such as ID, name, description, price, SKU, and category. | ||
/// </summary> | ||
/// <returns>A <see cref="RequestInformation"/></returns> | ||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param> | ||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER | ||
#nullable enable | ||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder.ExportRequestBuilderGetQueryParameters>>? requestConfiguration = default) | ||
{ | ||
#nullable restore | ||
#else | ||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder.ExportRequestBuilderGetQueryParameters>> requestConfiguration = default) | ||
{ | ||
#endif | ||
var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); | ||
requestInfo.Configure(requestConfiguration); | ||
requestInfo.Headers.TryAdd("Accept", "application/problem+json"); | ||
return requestInfo; | ||
} | ||
/// <summary> | ||
/// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. | ||
/// </summary> | ||
/// <returns>A <see cref="global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder"/></returns> | ||
/// <param name="rawUrl">The raw URL to use for the request builder.</param> | ||
public global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder WithUrl(string rawUrl) | ||
{ | ||
return new global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder(rawUrl, RequestAdapter); | ||
} | ||
/// <summary> | ||
/// Exports the product data to a CSV file based on the provided keywords. The CSV file includes product details such as ID, name, description, price, SKU, and category. | ||
/// </summary> | ||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] | ||
public partial class ExportRequestBuilderGetQueryParameters | ||
{ | ||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER | ||
#nullable enable | ||
[QueryParameter("keywords")] | ||
public string? Keywords { get; set; } | ||
#nullable restore | ||
#else | ||
[QueryParameter("keywords")] | ||
public string Keywords { get; set; } | ||
#endif | ||
} | ||
/// <summary> | ||
/// Configuration for the request such as headers, query parameters, and middleware options. | ||
/// </summary> | ||
[Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")] | ||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] | ||
public partial class ExportRequestBuilderGetRequestConfiguration : RequestConfiguration<global::CleanAspire.Api.Client.Products.Export.ExportRequestBuilder.ExportRequestBuilderGetQueryParameters> | ||
{ | ||
} | ||
} | ||
} | ||
#pragma warning restore CS0618 |
Oops, something went wrong.