Skip to content

Commit

Permalink
New - Exposition de ProducerProducts pour tous les utilisateurs
Browse files Browse the repository at this point in the history
  • Loading branch information
noelmugnier committed Feb 12, 2021
1 parent ad2a7f0 commit 0256998
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 52 deletions.
4 changes: 0 additions & 4 deletions Sheaft.Application.Tests/Sheaft.Application.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
<PackageReference Include="coverlet.collector" Version="1.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ public interface IProductQueries
{
Task<ProductsSearchDto> SearchAsync(SearchProductsInput terms, RequestUser currentUser, CancellationToken token);
Task<bool> ProductIsRatedByUserAsync(Guid id, Guid userId, RequestUser user, CancellationToken token);
IQueryable<ProductDto> GetStoreProducts(Guid storeId, RequestUser currentUser);
IQueryable<ProductDto> GetProducerProductsForStores(Guid producerId, RequestUser currentUser);
IQueryable<ProductDto> GetProduct(Guid id, RequestUser currentUser);
IQueryable<ProductDto> GetProducts(RequestUser currentUser);
IQueryable<ProductDto> GetProducerProducts(Guid producerId, RequestUser currentUser);
}
}
130 changes: 95 additions & 35 deletions Sheaft.Application/Product/Queries/ProductQueries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,39 @@ public class ProductQueries : IProductQueries
{
private readonly ISearchIndexClient _indexClient;
private readonly IAppDbContext _context;
private readonly RoleOptions _roleOptions;
private readonly AutoMapper.IConfigurationProvider _configurationProvider;

public ProductQueries(IAppDbContext context, IOptionsSnapshot<SearchOptions> searchOptions, ISearchServiceClient searchServiceClient, AutoMapper.IConfigurationProvider configurationProvider)
public ProductQueries(
IAppDbContext context,
IOptionsSnapshot<SearchOptions> searchOptions,
IOptionsSnapshot<RoleOptions> roleOptions,
ISearchServiceClient searchServiceClient,
AutoMapper.IConfigurationProvider configurationProvider)
{
_context = context;
_roleOptions = roleOptions.Value;
_configurationProvider = configurationProvider;
_indexClient = searchServiceClient.Indexes.GetClient(searchOptions.Value.Indexes.Products);
}

public async Task<ProductsSearchDto> SearchAsync(SearchProductsInput terms, RequestUser currentUser, CancellationToken token)
public async Task<ProductsSearchDto> SearchAsync(SearchProductsInput terms, RequestUser currentUser,
CancellationToken token)
{
var sp = new SearchParameters()
{
SearchMode = SearchMode.Any,
Top = terms.Take,
Skip = (terms.Page - 1) * terms.Take,
SearchFields = new List<string> { "partialProductName"},
SearchFields = new List<string> {"partialProductName"},
Select = new List<string>()
{
"product_id", "product_name", "product_onSalePricePerUnit", "product_onSalePrice", "product_rating", "product_ratings_count", "product_image", "product_tags", "producer_id", "producer_name", "producer_email", "producer_phone", "producer_zipcode", "producer_city", "producer_longitude", "producer_latitude", "product_returnable", "product_unit", "product_quantityPerUnit", "product_conditioning", "product_available"
},
{
"product_id", "product_name", "product_onSalePricePerUnit", "product_onSalePrice", "product_rating",
"product_ratings_count", "product_image", "product_tags", "producer_id", "producer_name",
"producer_email", "producer_phone", "producer_zipcode", "producer_city", "producer_longitude",
"producer_latitude", "product_returnable", "product_unit", "product_quantityPerUnit",
"product_conditioning", "product_available"
},
IncludeTotalResultCount = true,
HighlightFields = new List<string>(),
HighlightPreTag = "<b>",
Expand All @@ -55,11 +67,14 @@ public async Task<ProductsSearchDto> SearchAsync(SearchProductsInput terms, Requ
{
if (terms.Sort.Contains("producer_geolocation") && terms.Longitude.HasValue && terms.Latitude.HasValue)
{
sp.OrderBy = new List<string>(){ $"geo.distance(producer_geolocation, geography'POINT({terms.Longitude.Value.ToString(new CultureInfo("en-US"))} {terms.Latitude.Value.ToString(new CultureInfo("en-US"))})')" };
sp.OrderBy = new List<string>()
{
$"geo.distance(producer_geolocation, geography'POINT({terms.Longitude.Value.ToString(new CultureInfo("en-US"))} {terms.Latitude.Value.ToString(new CultureInfo("en-US"))})')"
};
}
else if (!terms.Sort.Contains("producer_geolocation"))
{
sp.OrderBy = new List<string>() { terms.Sort };
sp.OrderBy = new List<string>() {terms.Sort};
}
}

Expand All @@ -78,7 +93,8 @@ public async Task<ProductsSearchDto> SearchAsync(SearchProductsInput terms, Requ
if (terms.Longitude.HasValue && terms.Latitude.HasValue)
{
filter += " and ";
filter += $"geo.distance(producer_geolocation, geography'POINT({terms.Longitude.Value.ToString(new CultureInfo("en-US"))} {terms.Latitude.Value.ToString(new CultureInfo("en-US"))})') le {terms.MaxDistance ?? 200}";
filter +=
$"geo.distance(producer_geolocation, geography'POINT({terms.Longitude.Value.ToString(new CultureInfo("en-US"))} {terms.Latitude.Value.ToString(new CultureInfo("en-US"))})') le {terms.MaxDistance ?? 200}";
}

sp.Filter = filter;
Expand All @@ -99,20 +115,32 @@ public async Task<ProductsSearchDto> SearchAsync(SearchProductsInput terms, Requ
{
Id = p.Product_id,
Name = p.Product_name,
ImageSmall = p.Product_image != null ? p.Product_image.EndsWith(".jpg") ? p.Product_image : p.Product_image + "_small.jpg" : string.Empty,
ImageMedium = p.Product_image != null ? p.Product_image.EndsWith(".jpg") ? p.Product_image : p.Product_image + "_medium.jpg" : string.Empty,
ImageLarge = p.Product_image != null ? p.Product_image.EndsWith(".jpg") ? p.Product_image : p.Product_image + "_large.jpg" : string.Empty,
Picture = p.Product_image != null ? p.Product_image.EndsWith(".jpg") ? p.Product_image : p.Product_image + "_medium.jpg" : string.Empty,
ImageSmall = p.Product_image != null
? p.Product_image.EndsWith(".jpg") ? p.Product_image : p.Product_image + "_small.jpg"
: string.Empty,
ImageMedium = p.Product_image != null
? p.Product_image.EndsWith(".jpg") ? p.Product_image : p.Product_image + "_medium.jpg"
: string.Empty,
ImageLarge = p.Product_image != null
? p.Product_image.EndsWith(".jpg") ? p.Product_image : p.Product_image + "_large.jpg"
: string.Empty,
Picture = p.Product_image != null
? p.Product_image.EndsWith(".jpg") ? p.Product_image : p.Product_image + "_medium.jpg"
: string.Empty,
OnSalePrice = p.Product_onSalePrice ?? 0,
OnSalePricePerUnit = p.Product_onSalePricePerUnit ?? 0,
QuantityPerUnit = p.Product_quantityPerUnit ?? 0,
Rating = p.Product_rating,
IsReturnable = p.Product_returnable ?? false,
RatingsCount = p.Product_ratings_count,
Available = p.Product_available ?? true,
Tags = p.Product_tags?.Select(t => new TagDto { Name = t }) ?? new List<TagDto>(),
Unit = !string.IsNullOrWhiteSpace(p.Product_unit) ? Enum.Parse<UnitKind>(p.Product_unit.ToLowerInvariant(), true) : UnitKind.NotSpecified,
Conditioning = !string.IsNullOrWhiteSpace(p.Product_conditioning) ? Enum.Parse<ConditioningKind>(p.Product_conditioning, true) : ConditioningKind.Not_Specified,
Tags = p.Product_tags?.Select(t => new TagDto {Name = t}) ?? new List<TagDto>(),
Unit = !string.IsNullOrWhiteSpace(p.Product_unit)
? Enum.Parse<UnitKind>(p.Product_unit.ToLowerInvariant(), true)
: UnitKind.NotSpecified,
Conditioning = !string.IsNullOrWhiteSpace(p.Product_conditioning)
? Enum.Parse<ConditioningKind>(p.Product_conditioning, true)
: ConditioningKind.Not_Specified,
Producer = new BusinessProfileDto
{
Id = p.Producer_id,
Expand All @@ -131,41 +159,73 @@ public async Task<ProductsSearchDto> SearchAsync(SearchProductsInput terms, Requ
};
}

public IQueryable<ProductDto> GetStoreProducts(Guid storeId, RequestUser currentUser)
public IQueryable<ProductDto> GetProduct(Guid id, RequestUser currentUser)
{
var producerIds = _context.Agreements
.Get(c => c.Store.Id == storeId && c.Status == AgreementStatus.Accepted)
.Select(a => a.Delivery.Producer.Id);
if (currentUser.IsInRole(_roleOptions.Admin.Value) || currentUser.IsInRole(_roleOptions.Support.Value))
return _context.Products
.Get(c => c.Id == id)
.ProjectTo<ProductDto>(_configurationProvider);

return _context.Products
.Get(p => producerIds.Contains(p.Producer.Id) && p.VisibleToStores)
if (currentUser.IsInRole(_roleOptions.Store.Value))
return _context.Products
.Get(c => c.Id == id && c.VisibleToStores)
.ProjectTo<ProductDto>(_configurationProvider);
}

public IQueryable<ProductDto> GetProducerProductsForStores(Guid producerId, RequestUser currentUser)
{
return _context.Products
.Get(p => p.Producer.Id == producerId && p.VisibleToStores)
.ProjectTo<ProductDto>(_configurationProvider);
.Get(c => c.Id == id && c.VisibleToConsumers)
.ProjectTo<ProductDto>(_configurationProvider);
}

public IQueryable<ProductDto> GetProduct(Guid id, RequestUser currentUser)
public IQueryable<ProductDto> GetProducts(RequestUser currentUser)
{
return _context.Products
.Get(c => c.Id == id)
if (currentUser.IsInRole(_roleOptions.Admin.Value) || currentUser.IsInRole(_roleOptions.Support.Value))
return _context.Products
.Get()
.ProjectTo<ProductDto>(_configurationProvider);

if (currentUser.IsInRole(_roleOptions.Producer.Value))
return _context.Products
.Get(c => c.Producer.Id == currentUser.Id)
.ProjectTo<ProductDto>(_configurationProvider);

if (currentUser.IsInRole(_roleOptions.Store.Value))
{
var producerIds = _context.Agreements
.Get(c => c.Store.Id == currentUser.Id && c.Status == AgreementStatus.Accepted)
.Select(a => a.Delivery.Producer.Id);

return _context.Products
.Get(p => producerIds.Contains(p.Producer.Id) && p.VisibleToStores)
.ProjectTo<ProductDto>(_configurationProvider);
}

return _context.Products
.Get(c => c.VisibleToConsumers)
.ProjectTo<ProductDto>(_configurationProvider);
}

public IQueryable<ProductDto> GetProducts(RequestUser currentUser)
public IQueryable<ProductDto> GetProducerProducts(Guid producerId, RequestUser currentUser)
{
return _context.Products
.Get(c => c.Producer.Id == currentUser.Id)
if (currentUser.IsInRole(_roleOptions.Admin.Value) || currentUser.IsInRole(_roleOptions.Support.Value))
return _context.Products
.Get(p => p.Producer.Id == producerId)
.ProjectTo<ProductDto>(_configurationProvider);

if (currentUser.IsInRole(_roleOptions.Store.Value))
return _context.Products
.Get(p => p.Producer.Id == producerId && p.VisibleToStores)
.ProjectTo<ProductDto>(_configurationProvider);

return _context.Products
.Get(p => p.Producer.Id == producerId && p.VisibleToConsumers)
.ProjectTo<ProductDto>(_configurationProvider);
}

public async Task<bool> ProductIsRatedByUserAsync(Guid id, Guid userId, RequestUser user, CancellationToken token)
public async Task<bool> ProductIsRatedByUserAsync(Guid id, Guid userId, RequestUser user,
CancellationToken token)
{
return await _context.AnyAsync<Domain.Product>(p => p.Id == id && p.Ratings.Any(r => r.User.Id == userId), token);
return await _context.AnyAsync<Domain.Product>(p => p.Id == id && p.Ratings.Any(r => r.User.Id == userId),
token);
}

private class SearchProduct
Expand Down
4 changes: 2 additions & 2 deletions Sheaft.GraphQL/SheaftQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public IQueryable<UserProfileDto> GetMyUserProfile([Service] IUserQueries userQu
public IQueryable<ProductDto> GetStoreProducts([Service] IProductQueries productQueries)
{
SetLogTransaction(nameof(GetStoreProducts));
return productQueries.GetStoreProducts(CurrentUser.Id, CurrentUser);
return productQueries.GetProducts(CurrentUser);
}

public IQueryable<T> GetProducer<T>(Guid input, [Service] IProducerQueries producerQueries)
Expand Down Expand Up @@ -321,7 +321,7 @@ public IQueryable<ProductDto> GetProduct(Guid input, [Service] IProductQueries p
public IQueryable<ProductDto> GetProducerProducts(Guid input, [Service] IProductQueries productQueries)
{
SetLogTransaction(nameof(GetProducerProducts), input);
return productQueries.GetProducerProductsForStores(input, CurrentUser);
return productQueries.GetProducerProducts(input, CurrentUser);
}

public IQueryable<ProductDto> GetProducts([Service] IProductQueries productQueries)
Expand Down
1 change: 0 additions & 1 deletion Sheaft.GraphQL/Types/SheaftQueryType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ protected override void Configure(IObjectTypeDescriptor<SheaftQuery> descriptor)

descriptor.Field(c => c.GetProducerProducts(default, default))
.Name("producerProducts")
.Authorize(Policies.STORE)
.Argument("input", c => c.Type<NonNullType<IdType>>())
.Type<NonNullType<ListType<ProductType>>>()
.UsePaging<ProductType>()
Expand Down
6 changes: 3 additions & 3 deletions Sheaft.Web.Jobs/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,11 @@ public void ConfigureServices(IServiceCollection services)
services.AddScoped<IPspService, PspService>();
services.AddScoped<IFeesService, FeesService>();
services.AddScoped<ICapingDeliveriesService, CapingDeliveriesService>();
services.AddScoped<ISheaftMediatr, SheaftMediatr>();
services.AddScoped<IAuthService, AuthService>();
services.AddSingleton<IBackgroundJobClient, BackgroundJobClient>();
services.AddSingleton<ICurrentUserService, CurrentUserService>();
services.AddScoped<ISheaftHangfireBridge, SheaftHangfireBridge>();
services.AddScoped<IBackgroundJobClient, BackgroundJobClient>();
services.AddSingleton<ISheaftMediatr, SheaftMediatr>();
services.AddSingleton<ISheaftHangfireBridge, SheaftHangfireBridge>();

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>));
Expand Down
8 changes: 3 additions & 5 deletions Sheaft.Web.Manage/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,6 @@ public void ConfigureServices(IServiceCollection services)

services.AddMediatR(new List<Assembly>() { typeof(RegisterStoreCommand).Assembly }.ToArray());

services.AddScoped<IBackgroundJobClient, BackgroundJobClient>();
services.AddScoped<ISheaftHangfireBridge, SheaftHangfireBridge>();

var jobsDatabaseConfig = jobsDatabaseSettings.Get<JobsDatabaseOptions>();
services.AddHangfire(configuration =>
{
Expand Down Expand Up @@ -251,11 +248,12 @@ public void ConfigureServices(IServiceCollection services)
services.AddScoped<ISignalrService, SignalrService>();
services.AddScoped<IPictureService, PictureService>();
services.AddScoped<IPspService, PspService>();
services.AddScoped<ISheaftMediatr, SheaftMediatr>();
services.AddScoped<IAuthService, AuthService>();
services.AddSingleton<ICurrentUserService, CurrentUserService>();
services.AddScoped<IFeesService, FeesService>();
services.AddScoped<ICapingDeliveriesService, CapingDeliveriesService>();
services.AddSingleton<IBackgroundJobClient, BackgroundJobClient>();
services.AddSingleton<ICurrentUserService, CurrentUserService>();
services.AddSingleton<ISheaftMediatr, SheaftMediatr>();

services.AddScoped<IAgreementQueries, AgreementQueries>();
services.AddScoped<IProducerQueries, ProducerQueries>();
Expand Down

0 comments on commit 0256998

Please sign in to comment.