Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VCST-1853: Add Product Review XAPI Middleware #62

Merged
merged 4 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/VirtoCommerce.CustomerReviews.Core/ModuleConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

namespace VirtoCommerce.CustomerReviews.Core
{
public static class ReviewEntityTypes
{
public const string Product = "Product";
}

public static class ModuleConstants
{
public static class Security
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Threading.Tasks;
using Hangfire;
using VirtoCommerce.CustomerReviews.Core;
using VirtoCommerce.CustomerReviews.Data.Models;
using VirtoCommerce.CustomerReviews.Data.Repositories;
using VirtoCommerce.OrdersModule.Core.Events;
Expand Down Expand Up @@ -82,7 +83,7 @@ public virtual async Task TryToSendOrderNotificationsAsync(OrderRequestReviewJob
CustomerOrderId = jobArgument.CustomerOrderId,
ModifiedDate = DateTime.Now,
EntityId = item.ProductId,
EntityType = "Product",
EntityType = ReviewEntityTypes.Product,
ReviewsRequest = 0,
StoreId = jobArgument.StoreId,
UserId = jobArgument.CustomerId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using VirtoCommerce.CustomerReviews.Core;
using VirtoCommerce.CustomerReviews.Data.Models;
using VirtoCommerce.Platform.Data.Infrastructure;

Expand Down Expand Up @@ -70,7 +71,7 @@ public async Task<IList<RequestReviewEntity>> GetReviewsWithEmptyAccessDate(Date
!CustomerReviews.Any(cr =>
r.StoreId == cr.StoreId &&
r.EntityId == cr.EntityId &&
r.EntityType == "Product" &&
r.EntityType == ReviewEntityTypes.Product &&
cr.UserId == r.UserId))
.ToListAsync();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using VirtoCommerce.CustomerReviews.Core;
using VirtoCommerce.CustomerReviews.Core.Models;
using VirtoCommerce.CustomerReviews.Core.Services;
using VirtoCommerce.CustomerReviews.Data.Models;
Expand Down Expand Up @@ -40,7 +41,7 @@ public RatingService(

public Task CalculateAsync(string storeId)
{
return Calculate(storeId, null, "Product");
return Calculate(storeId, null, ReviewEntityTypes.Product);
}

public async Task CalculateAsync(ReviewStatusChangeData[] data)
Expand Down Expand Up @@ -119,7 +120,7 @@ public async Task<RatingProductDto[]> GetForStoreAsync(string storeId, string[]
{
using (var repository = _repositoryFactory())
{
var ratings = await repository.GetAsync(storeId, productIds, "Product");
var ratings = await repository.GetAsync(storeId, productIds, ReviewEntityTypes.Product);

return ratings.Select(x => new RatingProductDto
{
Expand Down Expand Up @@ -165,7 +166,7 @@ public async Task<RatingStoreDto[]> GetForCatalogAsync(string catalogId, string[

foreach (var store in stores)
{
var ratings = await repository.GetAsync(store.Id, productIds, "Product");
var ratings = await repository.GetAsync(store.Id, productIds, ReviewEntityTypes.Product);
if (ratings.Any())
{
result.AddRange(ratings.Select(x => new RatingStoreDto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public static IServiceCollection AddExperienceApi(this IServiceCollection servic
serviceCollection.AddSchemaBuilders(assemblyMarker);
serviceCollection.AddPipeline<SearchProductResponse>(builder =>
{
builder.AddMiddleware(typeof(EvalProductRatingMiddleware));
builder.AddMiddleware(typeof(EvalProductVendorRatingMiddleware));
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using PipelineNet.Middleware;
using VirtoCommerce.CustomerReviews.Core;
using VirtoCommerce.CustomerReviews.Core.Models;
using VirtoCommerce.CustomerReviews.Core.Services;
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Xapi.Core.Models;
using VirtoCommerce.XCatalog.Core.Models;
using VirtoCommerce.XDigitalCatalog.Queries;

namespace VirtoCommerce.CustomerReviews.ExperienceApi.Middleware;

public class EvalProductRatingMiddleware : IAsyncMiddleware<SearchProductResponse>
{
private readonly IMapper _mapper;
private readonly IRatingService _ratingService;

public EvalProductRatingMiddleware(IMapper mapper, IRatingService ratingService)
{
_mapper = mapper;
_ratingService = ratingService;
}

public virtual async Task Run(SearchProductResponse parameter, Func<SearchProductResponse, Task> next)
{
if (parameter == null)
{
throw new ArgumentNullException(nameof(parameter));
}

var query = parameter.Query;
if (query == null)
{
throw new OperationCanceledException("Query must be set");
}

var responseGroup = EnumUtility.SafeParse(query.GetResponseGroup(), ExpProductResponseGroup.None);
if (responseGroup.HasFlag(ExpProductResponseGroup.LoadRating) && parameter.Results.Any())
{
await LoadProductRaiting(parameter, query);
}

await next(parameter);
}

protected virtual async Task LoadProductRaiting(SearchProductResponse parameter, SearchProductQuery query)
{
var productIds = parameter.Results.Select(product => product.Id).ToArray();
var ratings = await _ratingService.GetForStoreAsync(query.StoreId, productIds, ReviewEntityTypes.Product);

var ratingByIds = new Dictionary<string, RatingEntityDto>();
foreach (var rating in ratings)
{
ratingByIds.Add(rating.EntityId, rating);
}

if (ratingByIds.Count != 0)
{
parameter.Results
.Apply(product =>
{
if (ratingByIds.TryGetValue(product.Id, out var rating))
{
product.Rating = _mapper.Map<ExpRating>(rating);
}
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Xapi.Core.Models;
using VirtoCommerce.XCatalog.Core.Models;
using VirtoCommerce.XDigitalCatalog.Queries;

namespace VirtoCommerce.CustomerReviews.ExperienceApi.Middleware;

Expand Down Expand Up @@ -39,34 +40,39 @@ public virtual async Task Run(SearchProductResponse parameter, Func<SearchProduc
var responseGroup = EnumUtility.SafeParse(query.GetResponseGroup(), ExpProductResponseGroup.None);
if (responseGroup.HasFlag(ExpProductResponseGroup.LoadRating) && parameter.Results.Any())
{
var vendors = parameter.Results.Where(product => product.Vendor != null).Select(product => product.Vendor).ToArray();
await LoadVendorRaiting(parameter, query);
}

var ratingByIds = new Dictionary<(string, string), RatingEntityDto>();
await next(parameter);
}

foreach (var vendorsByType in vendors.GroupBy(vendor => vendor.Type))
{
var vendorType = vendorsByType.Key;
var vendorIds = vendorsByType.Select(vendor => vendor.Id).Distinct().ToArray();
var ratings = await _ratingService.GetForStoreAsync(query.StoreId, vendorIds, vendorType);
protected virtual async Task LoadVendorRaiting(SearchProductResponse parameter, SearchProductQuery query)
{
var vendors = parameter.Results.Where(product => product.Vendor != null).Select(product => product.Vendor).ToArray();

foreach (var rating in ratings)
{
ratingByIds.Add((rating.EntityId, rating.EntityType), rating);
}
}
var ratingByIds = new Dictionary<(string, string), RatingEntityDto>();

if (ratingByIds.Any())
foreach (var vendorsByType in vendors.GroupBy(vendor => vendor.Type))
{
var vendorType = vendorsByType.Key;
var vendorIds = vendorsByType.Select(vendor => vendor.Id).Distinct().ToArray();
var ratings = await _ratingService.GetForStoreAsync(query.StoreId, vendorIds, vendorType);

foreach (var rating in ratings)
{
parameter.Results
.Where(product => product.Vendor != null)
.Apply(product =>
{
ratingByIds.TryGetValue((product.Vendor.Id, product.Vendor.Type), out var rating);
product.Vendor.Rating = _mapper.Map<ExpRating>(rating);
});
ratingByIds.Add((rating.EntityId, rating.EntityType), rating);
}
}

await next(parameter);
if (ratingByIds.Any())
{
parameter.Results
.Where(product => product.Vendor != null)
.Apply(product =>
{
ratingByIds.TryGetValue((product.Vendor.Id, product.Vendor.Type), out var rating);
product.Vendor.Rating = _mapper.Map<ExpRating>(rating);
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="VirtoCommerce.Xapi.Core" Version="3.800.0" />
<PackageReference Include="VirtoCommerce.ProfileExperienceApiModule.Data" Version="3.809.0" />
<PackageReference Include="VirtoCommerce.XCatalog.Core" Version="3.800.0" />
<PackageReference Include="VirtoCommerce.XCatalog.Core" Version="3.808.0-alpha.26-vcst-1853-product-rating" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VirtoCommerce.CustomerReviews.Core\VirtoCommerce.CustomerReviews.Core.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public async Task<ActionResult<CustomerReviewListItemSearchResult>> GetCustomerR
foreach (var review in reviews.Results)
{
var listItem = new CustomerReviewListItem(review);
if (review.EntityType == "Product")
if (review.EntityType == ReviewEntityTypes.Product)
{
listItem.StoreName = stores.FirstOrDefault(s => s.Id == review.StoreId)?.Name;
}
Expand Down
Loading