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

DL-60: Refactor basic logic into basic crud/search services #166

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using VirtoCommerce.Platform.Caching;
using VirtoCommerce.Platform.Core.Caching;
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Platform.Core.Events;
using VirtoCommerce.Platform.Core.GenericCrud;
using VirtoCommerce.Platform.Data.GenericCrud;
using VirtoCommerce.PricingModule.Core.Model;
using VirtoCommerce.PricingModule.Data.Model;
using VirtoCommerce.PricingModule.Data.Repositories;

namespace VirtoCommerce.PricingModule.Data.Services.Crud.Basic
{
public class BasicPriceService<TModel, TEntity, TChangeEvent, TChangedEvent, TPriceListModel> : CrudService<TModel, TEntity, TChangeEvent, TChangedEvent>
where TModel : Price
where TEntity : PriceEntity, Platform.Core.Domain.IDataEntity<TEntity, TModel>
where TChangeEvent : GenericChangedEntryEvent<TModel>
where TChangedEvent : GenericChangedEntryEvent<TModel>
where TPriceListModel : Pricelist
{
private readonly ICrudService<TPriceListModel> _pricelistService;
public BasicPriceService(Func<IPricingRepository> repositoryFactory, IPlatformMemoryCache platformMemoryCache, IEventPublisher eventPublisher, ICrudService<TPriceListModel> pricelistService)
: base(repositoryFactory, platformMemoryCache, eventPublisher)
{
_pricelistService = pricelistService;
}

public override async Task SaveChangesAsync(IEnumerable<TModel> models)
{
var pkMap = new PrimaryKeyResolvingMap();
var changedEntries = new List<GenericChangedEntry<TModel>>();
using (var repository = _repositoryFactory())
{
var alreadyExistPricesEntities = await LoadEntities(repository, models.Select(x => x.Id).Where(x => x != null).Distinct().ToList());

//Create default priceLists for prices without pricelist
foreach (var priceWithoutPricelistGroup in models.Where(x => x.PricelistId == null).GroupBy(x => x.Currency))
{
var defaultPriceListId = GetDefaultPriceListName(priceWithoutPricelistGroup.Key);
var pricelists = await _pricelistService.GetAsync(new List<string> { defaultPriceListId });
if (pricelists.IsNullOrEmpty())
{
repository.Add(AbstractTypeFactory<PricelistEntity>.TryCreateInstance().FromModel(GetDefaultPriceList(priceWithoutPricelistGroup, defaultPriceListId), pkMap));
}
foreach (var priceWithoutPricelist in priceWithoutPricelistGroup)
{
priceWithoutPricelist.PricelistId = defaultPriceListId;
}
}

foreach (var price in models)
{
var sourceEntity = AbstractTypeFactory<TEntity>.TryCreateInstance().FromModel(price, pkMap);
var targetEntity = alreadyExistPricesEntities.FirstOrDefault(x => x.Id == price.Id);
if (targetEntity != null)
{
changedEntries.Add(new GenericChangedEntry<TModel>(price, (TModel)targetEntity.ToModel(AbstractTypeFactory<TModel>.TryCreateInstance()), EntryState.Modified));
sourceEntity.Patch(targetEntity);
}
else
{
changedEntries.Add(new GenericChangedEntry<TModel>(price, EntryState.Added));
repository.Add(sourceEntity);
}
}

await _eventPublisher.Publish(EventFactory<TChangeEvent>(changedEntries));

await repository.UnitOfWork.CommitAsync();
pkMap.ResolvePrimaryKeys();

ClearCache(models);

await _eventPublisher.Publish(EventFactory<TChangedEvent>(changedEntries));
}
}

protected override async Task<IEnumerable<TEntity>> LoadEntities(IRepository repository, IEnumerable<string> ids, string responseGroup)
{
return (IEnumerable<TEntity>)await ((IPricingRepository)repository).GetPricesByIdsAsync(ids);
}

protected override void ClearCache(IEnumerable<TModel> models)
{
GenericCachingRegion<TModel>.ExpireRegion();
base.ClearCache(models);
}

protected virtual Pricelist GetDefaultPriceList(IGrouping<string, TModel> priceWithoutPricelistGroup, string defaultPriceListId)
{
var defaultPriceList = AbstractTypeFactory<TPriceListModel>.TryCreateInstance();
defaultPriceList.Id = defaultPriceListId;
defaultPriceList.Currency = priceWithoutPricelistGroup.Key;
defaultPriceList.Name = defaultPriceListId;
defaultPriceList.Description = defaultPriceListId;
return defaultPriceList;
}
private string GetDefaultPriceListName(string currency)
{
var result = "Default" + currency;
return result;
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentValidation;
using VirtoCommerce.Platform.Caching;
using VirtoCommerce.Platform.Core.Caching;
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Platform.Core.Events;
using VirtoCommerce.Platform.Data.GenericCrud;
using VirtoCommerce.PricingModule.Core.Model;
using VirtoCommerce.PricingModule.Data.Model;
using VirtoCommerce.PricingModule.Data.Repositories;

namespace VirtoCommerce.PricingModule.Data.Services.Crud.Basic
{
public class BasicPricelistAssignmentService<TModel, TEntity, TChangeEvent, TChangedEvent> : CrudService<TModel, TEntity, TChangeEvent, TChangedEvent>
where TModel : PricelistAssignment
where TEntity : PricelistAssignmentEntity, Platform.Core.Domain.IDataEntity<TEntity, TModel>
where TChangeEvent : GenericChangedEntryEvent<TModel>
where TChangedEvent : GenericChangedEntryEvent<TModel>
{
private readonly AbstractValidator<IEnumerable<TModel>> _validator;

public BasicPricelistAssignmentService(Func<IPricingRepository> repositoryFactory,
IPlatformMemoryCache platformMemoryCache,
IEventPublisher eventPublisher,
AbstractValidator<IEnumerable<TModel>> validator)
: base(repositoryFactory, platformMemoryCache, eventPublisher)
{
_validator = validator;
}

protected override async Task<IEnumerable<TEntity>> LoadEntities(IRepository repository, IEnumerable<string> ids, string responseGroup)
{
return (IEnumerable<TEntity>)await ((IPricingRepository)repository).GetPricelistAssignmentsByIdAsync(ids);
}

protected override Task BeforeSaveChanges(IEnumerable<TModel> models)
{
_validator.ValidateAndThrow(models);

return base.BeforeSaveChanges(models);
}

protected override void ClearCache(IEnumerable<TModel> models)
{
foreach (var assignment in models)
{
GenericCachingRegion<TModel>.ExpireTokenForKey(assignment.Id);
GenericCachingRegion<Pricelist>.ExpireTokenForKey(assignment.PricelistId);
}
GenericSearchCachingRegion<TModel>.ExpireRegion();
GenericCachingRegion<TModel>.ExpireRegion();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using VirtoCommerce.Platform.Core.Caching;
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Platform.Core.Events;
using VirtoCommerce.Platform.Data.GenericCrud;
using VirtoCommerce.PricingModule.Core.Model;
using VirtoCommerce.PricingModule.Data.Model;
using VirtoCommerce.PricingModule.Data.Repositories;

namespace VirtoCommerce.PricingModule.Data.Services.Crud.Basic
{
public class BasicPricelistService<TModel, TEntity, TChangeEvent, TChangedEvent> : CrudService<TModel, TEntity, TChangeEvent, TChangedEvent>
where TModel : Pricelist
where TEntity : PricelistEntity, Platform.Core.Domain.IDataEntity<TEntity, TModel>
where TChangeEvent : GenericChangedEntryEvent<TModel>
where TChangedEvent : GenericChangedEntryEvent<TModel>
{
public BasicPricelistService(Func<IPricingRepository> repositoryFactory, IPlatformMemoryCache platformMemoryCache, IEventPublisher eventPublisher)
: base(repositoryFactory, platformMemoryCache, eventPublisher)
{
}

protected override async Task<IEnumerable<TEntity>> LoadEntities(IRepository repository, IEnumerable<string> ids, string responseGroup)
{
return (IEnumerable<TEntity>)await ((IPricingRepository)repository).GetPricelistByIdsAsync(ids, responseGroup);
}
}
}
90 changes: 3 additions & 87 deletions src/VirtoCommerce.PricingModule.Data/Services/Crud/PriceService.cs
Original file line number Diff line number Diff line change
@@ -1,104 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using VirtoCommerce.Platform.Caching;
using VirtoCommerce.Platform.Core.Caching;
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Platform.Core.Events;
using VirtoCommerce.Platform.Core.GenericCrud;
using VirtoCommerce.Platform.Data.GenericCrud;
using VirtoCommerce.PricingModule.Core.Events;
using VirtoCommerce.PricingModule.Core.Model;
using VirtoCommerce.PricingModule.Data.Model;
using VirtoCommerce.PricingModule.Data.Repositories;
using VirtoCommerce.PricingModule.Data.Services.Crud.Basic;

namespace VirtoCommerce.PricingModule.Data.Services
{
public class PriceService : CrudService<Price, PriceEntity, PriceChangingEvent, PriceChangedEvent>
public class PriceService : BasicPriceService<Price, PriceEntity, PriceChangingEvent, PriceChangedEvent, Pricelist>
{
private readonly ICrudService<Pricelist> _pricelistService;
public PriceService(Func<IPricingRepository> repositoryFactory, IPlatformMemoryCache platformMemoryCache, IEventPublisher eventPublisher, ICrudService<Pricelist> pricelistService)
: base(repositoryFactory, platformMemoryCache, eventPublisher)
: base(repositoryFactory, platformMemoryCache, eventPublisher, pricelistService)
{
_pricelistService = pricelistService;
}


public override async Task SaveChangesAsync(IEnumerable<Price> models)
{
var pkMap = new PrimaryKeyResolvingMap();
var changedEntries = new List<GenericChangedEntry<Price>>();
using (var repository = _repositoryFactory())
{
var alreadyExistPricesEntities = await LoadEntities(repository, models.Select(x => x.Id).Where(x => x != null).Distinct().ToList());

//Create default priceLists for prices without pricelist
foreach (var priceWithoutPricelistGroup in models.Where(x => x.PricelistId == null).GroupBy(x => x.Currency))
{
var defaultPriceListId = GetDefaultPriceListName(priceWithoutPricelistGroup.Key);
var pricelists = await _pricelistService.GetByIdsAsync(new[] { defaultPriceListId });
if (pricelists.IsNullOrEmpty())
{
repository.Add(AbstractTypeFactory<PricelistEntity>.TryCreateInstance().FromModel(GetDefaultPriceList(priceWithoutPricelistGroup, defaultPriceListId), pkMap));
}
foreach (var priceWithoutPricelist in priceWithoutPricelistGroup)
{
priceWithoutPricelist.PricelistId = defaultPriceListId;
}
}

foreach (var price in models)
{
var sourceEntity = AbstractTypeFactory<PriceEntity>.TryCreateInstance().FromModel(price, pkMap);
var targetEntity = alreadyExistPricesEntities.FirstOrDefault(x => x.Id == price.Id);
if (targetEntity != null)
{
changedEntries.Add(new GenericChangedEntry<Price>(price, targetEntity.ToModel(AbstractTypeFactory<Price>.TryCreateInstance()), EntryState.Modified));
sourceEntity.Patch(targetEntity);
}
else
{
changedEntries.Add(new GenericChangedEntry<Price>(price, EntryState.Added));
repository.Add(sourceEntity);
}
}

await _eventPublisher.Publish(new PriceChangingEvent(changedEntries));

await repository.UnitOfWork.CommitAsync();
pkMap.ResolvePrimaryKeys();

ClearCache(models);

await _eventPublisher.Publish(new PriceChangedEvent(changedEntries));
}
}

protected override async Task<IEnumerable<PriceEntity>> LoadEntities(IRepository repository, IEnumerable<string> ids, string responseGroup)
{
return await ((IPricingRepository)repository).GetPricesByIdsAsync(ids);
}

protected override void ClearCache(IEnumerable<Price> models)
{
GenericCachingRegion<Price>.ExpireRegion();
base.ClearCache(models);
}

protected virtual Pricelist GetDefaultPriceList(IGrouping<string, Price> priceWithoutPricelistGroup, string defaultPriceListId)
{
var defaultPriceList = AbstractTypeFactory<Pricelist>.TryCreateInstance();
defaultPriceList.Id = defaultPriceListId;
defaultPriceList.Currency = priceWithoutPricelistGroup.Key;
defaultPriceList.Name = defaultPriceListId;
defaultPriceList.Description = defaultPriceListId;
return defaultPriceList;
}
private string GetDefaultPriceListName(string currency)
{
var result = "Default" + currency;
return result;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,53 +1,25 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentValidation;
using VirtoCommerce.Platform.Caching;
using VirtoCommerce.Platform.Core.Caching;
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Platform.Core.Events;
using VirtoCommerce.Platform.Data.GenericCrud;
using VirtoCommerce.PricingModule.Core.Events;
using VirtoCommerce.PricingModule.Core.Model;
using VirtoCommerce.PricingModule.Data.Model;
using VirtoCommerce.PricingModule.Data.Repositories;
using VirtoCommerce.PricingModule.Data.Services.Crud.Basic;

namespace VirtoCommerce.PricingModule.Data.Services
{
public class PricelistAssignmentService : CrudService<PricelistAssignment, PricelistAssignmentEntity, PricelistAssignmentChangingEvent, PricelistAssignmentChangedEvent>
public class PricelistAssignmentService : BasicPricelistAssignmentService<PricelistAssignment, PricelistAssignmentEntity, PricelistAssignmentChangingEvent, PricelistAssignmentChangedEvent>
{
private readonly AbstractValidator<IEnumerable<PricelistAssignment>> _validator;

public PricelistAssignmentService(Func<IPricingRepository> repositoryFactory,
IPlatformMemoryCache platformMemoryCache,
IEventPublisher eventPublisher,
AbstractValidator<IEnumerable<PricelistAssignment>> validator)
: base(repositoryFactory, platformMemoryCache, eventPublisher)
: base(repositoryFactory, platformMemoryCache, eventPublisher, validator)
{
_validator = validator;
}

protected override async Task<IEnumerable<PricelistAssignmentEntity>> LoadEntities(IRepository repository, IEnumerable<string> ids, string responseGroup)
{
return await ((IPricingRepository)repository).GetPricelistAssignmentsByIdAsync(ids);
}

protected override Task BeforeSaveChanges(IEnumerable<PricelistAssignment> models)
{
_validator.ValidateAndThrow(models);

return base.BeforeSaveChanges(models);
}

protected override void ClearCache(IEnumerable<PricelistAssignment> models)
{
foreach (var assignment in models)
{
GenericCachingRegion<PricelistAssignment>.ExpireTokenForKey(assignment.Id);
GenericCachingRegion<Pricelist>.ExpireTokenForKey(assignment.PricelistId);
}
GenericSearchCachingRegion<PricelistAssignment>.ExpireRegion();
GenericCachingRegion<PricelistAssignment>.ExpireRegion();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using VirtoCommerce.Platform.Core.Caching;
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Platform.Core.Events;
using VirtoCommerce.Platform.Data.GenericCrud;
using VirtoCommerce.PricingModule.Core.Events;
using VirtoCommerce.PricingModule.Core.Model;
using VirtoCommerce.PricingModule.Data.Model;
using VirtoCommerce.PricingModule.Data.Repositories;
using VirtoCommerce.PricingModule.Data.Services.Crud.Basic;

namespace VirtoCommerce.PricingModule.Data.Services
{
public class PricelistService : CrudService<Pricelist, PricelistEntity, PricelistChangingEvent, PricelistChangedEvent>
public class PricelistService : BasicPricelistService<Pricelist, PricelistEntity, PricelistChangingEvent, PricelistChangedEvent>
{
public PricelistService(Func<IPricingRepository> repositoryFactory, IPlatformMemoryCache platformMemoryCache, IEventPublisher eventPublisher)
: base(repositoryFactory, platformMemoryCache, eventPublisher)
{
}

protected override async Task<IEnumerable<PricelistEntity>> LoadEntities(IRepository repository, IEnumerable<string> ids, string responseGroup)
{
return await ((IPricingRepository)repository).GetPricelistByIdsAsync(ids, responseGroup);
}
}
}
Loading