Browse Source

Orders module should not depends on PaymentService module

Close #88
Fix entity synchronizer
Rename OrderPayment to EShopPayment
Add EShopPaymentEto and EShopPaymentItemEto
pull/96/head
gdlcf88 6 years ago
parent
commit
f3284d55f4
  1. 1
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp.EShop.Orders.Domain.csproj
  2. 4
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/EShopOrdersDomainModule.cs
  3. 6
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/IOrderPaymentChecker.cs
  4. 5
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/IOrderPaymentCompletedEventHandler.cs
  5. 4
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/IOrderPaymentCreatedEventHandler.cs
  6. 12
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderPaymentChecker.cs
  7. 26
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderPaymentCompletedEventHandler.cs
  8. 18
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderPaymentCreatedEventHandler.cs
  9. 4
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderPaymentInvalidException.cs
  10. 4
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Application.Contracts/EasyAbp/EShop/Payments/Payments/OrderPaymentAlreadyExistsException.cs
  11. 2
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Application/EasyAbp/EShop/Payments/Payments/BasicPayableCheckProvider.cs
  12. 10
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain.Shared/EasyAbp/EShop/Payments/Payments/OrderPaymentCompletedEto.cs
  13. 48
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain.Shared/EasyAbp/EShop/Payments/Payments/OrderPaymentEto.cs
  14. 35
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain.Shared/EasyAbp/EShop/Payments/Payments/OrderPaymentItemEto.cs
  15. 16
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain/EasyAbp/EShop/Payments/EShopPaymentsDomainModule.cs
  16. 124
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain/EasyAbp/EShop/Payments/Payments/PaymentSynchronizer.cs
  17. 3
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain/EasyAbp/EShop/Payments/PaymentsDomainAutoMapperProfile.cs
  18. 133
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain/EasyAbp/EShop/Payments/Refunds/RefundSynchronizer.cs
  19. 6
      modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.EntityFrameworkCore/EasyAbp/EShop/Payments/Refunds/RefundRepository.cs
  20. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderCreatedEventHandler.cs
  21. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderPaidEventHandler.cs

1
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp.EShop.Orders.Domain.csproj

@ -8,7 +8,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="EasyAbp.PaymentService.Domain.Shared" Version="1.1.7" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="3.0.4" /> <PackageReference Include="Volo.Abp.AutoMapper" Version="3.0.4" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="3.0.4" /> <PackageReference Include="Volo.Abp.Ddd.Domain" Version="3.0.4" />
<ProjectReference Include="..\..\..\EasyAbp.EShop.Payments\src\EasyAbp.EShop.Payments.Domain.Shared\EasyAbp.EShop.Payments.Domain.Shared.csproj" /> <ProjectReference Include="..\..\..\EasyAbp.EShop.Payments\src\EasyAbp.EShop.Payments.Domain.Shared\EasyAbp.EShop.Payments.Domain.Shared.csproj" />

4
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/EShopOrdersDomainModule.cs

@ -1,4 +1,6 @@
using EasyAbp.EShop.Orders.Orders; using EasyAbp.EShop.Orders.Orders;
using EasyAbp.EShop.Payments;
using EasyAbp.EShop.Products;
using EasyAbp.EShop.Stores; using EasyAbp.EShop.Stores;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
@ -10,6 +12,8 @@ namespace EasyAbp.EShop.Orders
{ {
[DependsOn( [DependsOn(
typeof(AbpAutoMapperModule), typeof(AbpAutoMapperModule),
typeof(EShopPaymentsDomainSharedModule),
typeof(EShopProductsDomainSharedModule),
typeof(EShopOrdersDomainSharedModule) typeof(EShopOrdersDomainSharedModule)
)] )]
public class EShopOrdersDomainModule : AbpModule public class EShopOrdersDomainModule : AbpModule

6
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/IOrderPaymentChecker.cs

@ -1,10 +1,10 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.PaymentService.Payments; using EasyAbp.EShop.Payments.Payments;
namespace EasyAbp.EShop.Orders.Orders namespace EasyAbp.EShop.Orders.Orders
{ {
public interface IOrderPaymentChecker public interface IEShopPaymentChecker
{ {
Task<bool> IsValidPaymentAsync(Order order, PaymentEto payment, PaymentItemEto paymentItem); Task<bool> IsValidPaymentAsync(Order order, EShopPaymentEto payment, EShopPaymentItemEto paymentItem);
} }
} }

5
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/IOrderPaymentCompletedEventHandler.cs

@ -1,10 +1,9 @@
using EasyAbp.PaymentService.Payments; using EasyAbp.EShop.Payments.Payments;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
namespace EasyAbp.EShop.Orders.Orders namespace EasyAbp.EShop.Orders.Orders
{ {
public interface IOrderPaymentCompletedEventHandler : IDistributedEventHandler<PaymentCompletedEto> public interface IEShopPaymentCompletedEventHandler : IDistributedEventHandler<EShopPaymentCompletedEto>
{ {
} }

4
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/IOrderPaymentCreatedEventHandler.cs

@ -1,10 +1,10 @@
using EasyAbp.PaymentService.Payments; using EasyAbp.EShop.Payments.Payments;
using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
namespace EasyAbp.EShop.Orders.Orders namespace EasyAbp.EShop.Orders.Orders
{ {
public interface IOrderPaymentCreatedEventHandler : IDistributedEventHandler<EntityCreatedEto<PaymentEto>> public interface IEShopPaymentCreatedEventHandler : IDistributedEventHandler<EntityCreatedEto<EShopPaymentEto>>
{ {
} }

12
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderPaymentChecker.cs

@ -1,33 +1,33 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.PaymentService.Payments; using EasyAbp.EShop.Payments.Payments;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace EasyAbp.EShop.Orders.Orders namespace EasyAbp.EShop.Orders.Orders
{ {
public class OrderPaymentChecker : IOrderPaymentChecker, ITransientDependency public class EShopPaymentChecker : IEShopPaymentChecker, ITransientDependency
{ {
public virtual async Task<bool> IsValidPaymentAsync(Order order, PaymentEto payment, PaymentItemEto paymentItem) public virtual async Task<bool> IsValidPaymentAsync(Order order, EShopPaymentEto payment, EShopPaymentItemEto paymentItem)
{ {
return await IsStoreIdCorrectAsync(order, paymentItem) && return await IsStoreIdCorrectAsync(order, paymentItem) &&
await IsPaymentPriceCorrectAsync(order, paymentItem) && await IsPaymentPriceCorrectAsync(order, paymentItem) &&
await IsUserAllowedToPayAsync(order, payment); await IsUserAllowedToPayAsync(order, payment);
} }
protected virtual Task<bool> IsStoreIdCorrectAsync(Order order, PaymentItemEto paymentItem) protected virtual Task<bool> IsStoreIdCorrectAsync(Order order, EShopPaymentItemEto paymentItem)
{ {
return Task.FromResult( return Task.FromResult(
Guid.TryParse(paymentItem.GetProperty<string>("StoreId"), out var paymentStoreId) && Guid.TryParse(paymentItem.GetProperty<string>("StoreId"), out var paymentStoreId) &&
order.StoreId == paymentStoreId); order.StoreId == paymentStoreId);
} }
protected virtual Task<bool> IsPaymentPriceCorrectAsync(Order order, PaymentItemEto paymentItem) protected virtual Task<bool> IsPaymentPriceCorrectAsync(Order order, EShopPaymentItemEto paymentItem)
{ {
return Task.FromResult(order.TotalPrice == paymentItem.OriginalPaymentAmount); return Task.FromResult(order.TotalPrice == paymentItem.OriginalPaymentAmount);
} }
protected virtual Task<bool> IsUserAllowedToPayAsync(Order order, PaymentEto payment) protected virtual Task<bool> IsUserAllowedToPayAsync(Order order, EShopPaymentEto payment)
{ {
return Task.FromResult(order.CustomerUserId == payment.UserId); return Task.FromResult(order.CustomerUserId == payment.UserId);
} }

26
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderPaymentCompletedEventHandler.cs

@ -2,9 +2,8 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.EShop.Payments; using EasyAbp.EShop.Payments;
using EasyAbp.PaymentService.Payments; using EasyAbp.EShop.Payments.Payments;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
@ -13,22 +12,22 @@ using Volo.Abp.Uow;
namespace EasyAbp.EShop.Orders.Orders namespace EasyAbp.EShop.Orders.Orders
{ {
public class OrderPaymentCompletedEventHandler : IOrderPaymentCompletedEventHandler, ITransientDependency public class EShopPaymentCompletedEventHandler : IEShopPaymentCompletedEventHandler, ITransientDependency
{ {
private readonly IClock _clock; private readonly IClock _clock;
private readonly ICurrentTenant _currentTenant; private readonly ICurrentTenant _currentTenant;
private readonly IObjectMapper _objectMapper; private readonly IObjectMapper _objectMapper;
private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IOrderPaymentChecker _orderPaymentChecker; private readonly IEShopPaymentChecker _eShopPaymentChecker;
private readonly IDistributedEventBus _distributedEventBus; private readonly IDistributedEventBus _distributedEventBus;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
public OrderPaymentCompletedEventHandler( public EShopPaymentCompletedEventHandler(
IClock clock, IClock clock,
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IObjectMapper objectMapper, IObjectMapper objectMapper,
IUnitOfWorkManager unitOfWorkManager, IUnitOfWorkManager unitOfWorkManager,
IOrderPaymentChecker orderPaymentChecker, IEShopPaymentChecker eShopPaymentChecker,
IDistributedEventBus distributedEventBus, IDistributedEventBus distributedEventBus,
IOrderRepository orderRepository) IOrderRepository orderRepository)
{ {
@ -36,12 +35,13 @@ namespace EasyAbp.EShop.Orders.Orders
_currentTenant = currentTenant; _currentTenant = currentTenant;
_objectMapper = objectMapper; _objectMapper = objectMapper;
_unitOfWorkManager = unitOfWorkManager; _unitOfWorkManager = unitOfWorkManager;
_orderPaymentChecker = orderPaymentChecker; _eShopPaymentChecker = eShopPaymentChecker;
_distributedEventBus = distributedEventBus; _distributedEventBus = distributedEventBus;
_orderRepository = orderRepository; _orderRepository = orderRepository;
} }
public virtual async Task HandleEventAsync(PaymentCompletedEto eventData) [UnitOfWork(true)]
public virtual async Task HandleEventAsync(EShopPaymentCompletedEto eventData)
{ {
var payment = eventData.Payment; var payment = eventData.Payment;
@ -52,8 +52,6 @@ namespace EasyAbp.EShop.Orders.Orders
using var currentTenant = _currentTenant.Change(payment.TenantId); using var currentTenant = _currentTenant.Change(payment.TenantId);
using var uow = _unitOfWorkManager.Begin(isTransactional: true);
foreach (var item in payment.PaymentItems.Where(item => item.ItemType == PaymentsConsts.PaymentItemType)) foreach (var item in payment.PaymentItems.Where(item => item.ItemType == PaymentsConsts.PaymentItemType))
{ {
var orderId = Guid.Parse(item.ItemKey); var orderId = Guid.Parse(item.ItemKey);
@ -66,9 +64,9 @@ namespace EasyAbp.EShop.Orders.Orders
throw new OrderIsInWrongStageException(order.Id); throw new OrderIsInWrongStageException(order.Id);
} }
if (!await _orderPaymentChecker.IsValidPaymentAsync(order, payment, item)) if (!await _eShopPaymentChecker.IsValidPaymentAsync(order, payment, item))
{ {
throw new OrderPaymentInvalidException(payment.Id, orderId); throw new EShopPaymentInvalidException(payment.Id, orderId);
} }
order.SetPaidTime(_clock.Now); order.SetPaidTime(_clock.Now);
@ -76,7 +74,7 @@ namespace EasyAbp.EShop.Orders.Orders
await _orderRepository.UpdateAsync(order, true); await _orderRepository.UpdateAsync(order, true);
uow.OnCompleted(async () => await _distributedEventBus.PublishAsync(new OrderPaidEto _unitOfWorkManager.Current.OnCompleted(async () => await _distributedEventBus.PublishAsync(new OrderPaidEto
{ {
Order = _objectMapper.Map<Order, OrderEto>(order), Order = _objectMapper.Map<Order, OrderEto>(order),
PaymentId = payment.Id, PaymentId = payment.Id,
@ -84,7 +82,7 @@ namespace EasyAbp.EShop.Orders.Orders
})); }));
} }
await uow.CompleteAsync(); await _unitOfWorkManager.Current.CompleteAsync();
} }
} }
} }

18
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderPaymentCreatedEventHandler.cs

@ -2,7 +2,7 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.EShop.Payments; using EasyAbp.EShop.Payments;
using EasyAbp.PaymentService.Payments; using EasyAbp.EShop.Payments.Payments;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
@ -10,24 +10,24 @@ using Volo.Abp.Uow;
namespace EasyAbp.EShop.Orders.Orders namespace EasyAbp.EShop.Orders.Orders
{ {
public class OrderPaymentCreatedEventHandler : IOrderPaymentCreatedEventHandler, ITransientDependency public class EShopPaymentCreatedEventHandler : IEShopPaymentCreatedEventHandler, ITransientDependency
{ {
private readonly ICurrentTenant _currentTenant; private readonly ICurrentTenant _currentTenant;
private readonly IOrderPaymentChecker _orderPaymentChecker; private readonly IEShopPaymentChecker _eShopPaymentChecker;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
public OrderPaymentCreatedEventHandler( public EShopPaymentCreatedEventHandler(
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IOrderPaymentChecker orderPaymentChecker, IEShopPaymentChecker eShopPaymentChecker,
IOrderRepository orderRepository) IOrderRepository orderRepository)
{ {
_currentTenant = currentTenant; _currentTenant = currentTenant;
_orderPaymentChecker = orderPaymentChecker; _eShopPaymentChecker = eShopPaymentChecker;
_orderRepository = orderRepository; _orderRepository = orderRepository;
} }
[UnitOfWork(true)] [UnitOfWork(true)]
public virtual async Task HandleEventAsync(EntityCreatedEto<PaymentEto> eventData) public virtual async Task HandleEventAsync(EntityCreatedEto<EShopPaymentEto> eventData)
{ {
using var currentTenant = _currentTenant.Change(eventData.Entity.TenantId); using var currentTenant = _currentTenant.Change(eventData.Entity.TenantId);
@ -43,10 +43,10 @@ namespace EasyAbp.EShop.Orders.Orders
throw new OrderIsInWrongStageException(order.Id); throw new OrderIsInWrongStageException(order.Id);
} }
if (!await _orderPaymentChecker.IsValidPaymentAsync(order, eventData.Entity, item)) if (!await _eShopPaymentChecker.IsValidPaymentAsync(order, eventData.Entity, item))
{ {
// Todo: should cancel the payment? // Todo: should cancel the payment?
throw new OrderPaymentInvalidException(eventData.Entity.Id, orderId); throw new EShopPaymentInvalidException(eventData.Entity.Id, orderId);
} }
order.SetPaymentId(eventData.Entity.Id); order.SetPaymentId(eventData.Entity.Id);

4
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderPaymentInvalidException.cs

@ -3,9 +3,9 @@ using Volo.Abp;
namespace EasyAbp.EShop.Orders.Orders namespace EasyAbp.EShop.Orders.Orders
{ {
public class OrderPaymentInvalidException : BusinessException public class EShopPaymentInvalidException : BusinessException
{ {
public OrderPaymentInvalidException(Guid paymentId, Guid orderId) public EShopPaymentInvalidException(Guid paymentId, Guid orderId)
: base(message: $"The payment {paymentId} has invalid configurations for the order {orderId}.") : base(message: $"The payment {paymentId} has invalid configurations for the order {orderId}.")
{ {
} }

4
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Application.Contracts/EasyAbp/EShop/Payments/Payments/OrderPaymentAlreadyExistsException.cs

@ -3,9 +3,9 @@ using Volo.Abp;
namespace EasyAbp.EShop.Payments.Payments namespace EasyAbp.EShop.Payments.Payments
{ {
public class OrderPaymentAlreadyExistsException : BusinessException public class EShopPaymentAlreadyExistsException : BusinessException
{ {
public OrderPaymentAlreadyExistsException(Guid orderId) public EShopPaymentAlreadyExistsException(Guid orderId)
: base(message: $"The order {orderId}'s payment is already exists.") : base(message: $"The order {orderId}'s payment is already exists.")
{ {
} }

2
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Application/EasyAbp/EShop/Payments/Payments/BasicPayableCheckProvider.cs

@ -14,7 +14,7 @@ namespace EasyAbp.EShop.Payments.Payments
{ {
foreach (var order in orders.Where(order => order.PaymentId.HasValue || order.PaidTime.HasValue)) foreach (var order in orders.Where(order => order.PaymentId.HasValue || order.PaidTime.HasValue))
{ {
throw new OrderPaymentAlreadyExistsException(order.Id); throw new EShopPaymentAlreadyExistsException(order.Id);
} }
if (orders.Select(order => order.Currency).Distinct().Count() != 1) if (orders.Select(order => order.Currency).Distinct().Count() != 1)

10
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain.Shared/EasyAbp/EShop/Payments/Payments/OrderPaymentCompletedEto.cs

@ -0,0 +1,10 @@
using System;
namespace EasyAbp.EShop.Payments.Payments
{
[Serializable]
public class EShopPaymentCompletedEto
{
public EShopPaymentEto Payment { get; set; }
}
}

48
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain.Shared/EasyAbp/EShop/Payments/Payments/OrderPaymentEto.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using EasyAbp.PaymentService.Payments;
using Volo.Abp.Data;
using Volo.Abp.MultiTenancy;
namespace EasyAbp.EShop.Payments.Payments
{
[Serializable]
public class EShopPaymentEto : IPayment, IMultiTenant, IHasExtraProperties
{
#region Base properties
public Guid Id { get; set; }
public Guid? TenantId { get; set; }
public Guid UserId { get; set; }
public string PaymentMethod { get; set; }
public string PayeeAccount { get; set; }
public string ExternalTradingCode { get; set; }
public string Currency { get; set; }
public decimal OriginalPaymentAmount { get; set; }
public decimal PaymentDiscount { get; set; }
public decimal ActualPaymentAmount { get; set; }
public decimal RefundAmount { get; set; }
public decimal PendingRefundAmount { get; set; }
public DateTime? CompletionTime { get; set; }
public DateTime? CanceledTime { get; set; }
public Dictionary<string, object> ExtraProperties { get; set; }
#endregion
public List<EShopPaymentItemEto> PaymentItems { get; set; } = new List<EShopPaymentItemEto>();
}
}

35
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain.Shared/EasyAbp/EShop/Payments/Payments/OrderPaymentItemEto.cs

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using EasyAbp.PaymentService.Payments;
using Volo.Abp.Data;
namespace EasyAbp.EShop.Payments.Payments
{
[Serializable]
public class EShopPaymentItemEto : IPaymentItem, IHasExtraProperties
{
#region Base properties
public Guid Id { get; set; }
public string ItemType { get; set; }
public string ItemKey { get; set; }
public decimal OriginalPaymentAmount { get; set; }
public decimal PaymentDiscount { get; set; }
public decimal ActualPaymentAmount { get; set; }
public decimal RefundAmount { get; set; }
public decimal PendingRefundAmount { get; set; }
public Dictionary<string, object> ExtraProperties { get; set; }
#endregion
public Guid StoreId { get; set; }
}
}

16
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain/EasyAbp/EShop/Payments/EShopPaymentsDomainModule.cs

@ -1,8 +1,6 @@
using EasyAbp.EShop.Payments.Payments; using EasyAbp.EShop.Payments.Payments;
using EasyAbp.EShop.Payments.Refunds; using EasyAbp.EShop.Payments.Refunds;
using EasyAbp.EShop.Stores; using EasyAbp.EShop.Stores;
using EasyAbp.PaymentService.Payments;
using EasyAbp.PaymentService.Refunds;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
@ -14,9 +12,21 @@ namespace EasyAbp.EShop.Payments
typeof(AbpAutoMapperModule), typeof(AbpAutoMapperModule),
typeof(EShopPaymentsDomainSharedModule), typeof(EShopPaymentsDomainSharedModule),
typeof(EShopStoresDomainSharedModule) typeof(EShopStoresDomainSharedModule)
)] )]
public class EShopPaymentsDomainModule : AbpModule public class EShopPaymentsDomainModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpDistributedEntityEventOptions>(options =>
{
options.EtoMappings.Add<Payment, EShopPaymentEto>(typeof(EShopPaymentsDomainModule));
options.EtoMappings.Add<Refund, OrderRefundEto>(typeof(EShopPaymentsDomainModule));
options.AutoEventSelectors.Add<Payment>();
options.AutoEventSelectors.Add<Refund>();
});
}
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
context.Services.AddAutoMapperObjectMapper<EShopPaymentsDomainModule>(); context.Services.AddAutoMapperObjectMapper<EShopPaymentsDomainModule>();

124
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain/EasyAbp/EShop/Payments/Payments/PaymentSynchronizer.cs

@ -14,6 +14,7 @@ using Volo.Abp.Uow;
namespace EasyAbp.EShop.Payments.Payments namespace EasyAbp.EShop.Payments.Payments
{ {
public class PaymentSynchronizer : public class PaymentSynchronizer :
IDistributedEventHandler<EntityCreatedEto<PaymentEto>>,
IDistributedEventHandler<EntityUpdatedEto<PaymentEto>>, IDistributedEventHandler<EntityUpdatedEto<PaymentEto>>,
IDistributedEventHandler<EntityDeletedEto<PaymentEto>>, IDistributedEventHandler<EntityDeletedEto<PaymentEto>>,
IPaymentSynchronizer, IPaymentSynchronizer,
@ -21,71 +22,132 @@ namespace EasyAbp.EShop.Payments.Payments
{ {
private readonly IObjectMapper _objectMapper; private readonly IObjectMapper _objectMapper;
private readonly ICurrentTenant _currentTenant; private readonly ICurrentTenant _currentTenant;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IPaymentRepository _paymentRepository; private readonly IPaymentRepository _paymentRepository;
private readonly IDistributedEventBus _distributedEventBus;
public PaymentSynchronizer( public PaymentSynchronizer(
IObjectMapper objectMapper, IObjectMapper objectMapper,
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IPaymentRepository paymentRepository) IUnitOfWorkManager unitOfWorkManager,
IPaymentRepository paymentRepository,
IDistributedEventBus distributedEventBus)
{ {
_objectMapper = objectMapper; _objectMapper = objectMapper;
_currentTenant = currentTenant; _currentTenant = currentTenant;
_unitOfWorkManager = unitOfWorkManager;
_paymentRepository = paymentRepository; _paymentRepository = paymentRepository;
_distributedEventBus = distributedEventBus;
} }
[UnitOfWork(true)] [UnitOfWork(true)]
public virtual async Task HandleEventAsync(EntityUpdatedEto<PaymentEto> eventData) public virtual async Task HandleEventAsync(EntityCreatedEto<PaymentEto> eventData)
{ {
if (eventData.Entity.PaymentItems.All(item => item.ItemType != PaymentsConsts.PaymentItemType))
{
return;
}
using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId); using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId);
var payment = await _paymentRepository.FindAsync(eventData.Entity.Id); var payment = await _paymentRepository.FindAsync(eventData.Entity.Id);
if (payment == null) if (payment != null)
{ {
payment = _objectMapper.Map<PaymentEto, Payment>(eventData.Entity); return;
}
payment = _objectMapper.Map<PaymentEto, Payment>(eventData.Entity);
payment.SetPaymentItems( payment.SetPaymentItems(
_objectMapper.Map<List<PaymentItemEto>, List<PaymentItem>>(eventData.Entity.PaymentItems)); _objectMapper.Map<List<PaymentItemEto>, List<PaymentItem>>(eventData.Entity.PaymentItems));
payment.PaymentItems.ForEach(FillPaymentItemStoreId);
await _paymentRepository.InsertAsync(payment, true); await _paymentRepository.InsertAsync(payment, true);
if (payment.CompletionTime.HasValue)
{
_unitOfWorkManager.Current.OnCompleted(async () =>
{
await _distributedEventBus.PublishAsync(new EShopPaymentCompletedEto
{
Payment = _objectMapper.Map<Payment, EShopPaymentEto>(payment)
});
});
} }
else }
[UnitOfWork(true)]
public virtual async Task HandleEventAsync(EntityUpdatedEto<PaymentEto> eventData)
{
if (eventData.Entity.PaymentItems.All(item => item.ItemType != PaymentsConsts.PaymentItemType))
{ {
_objectMapper.Map(eventData.Entity, payment); return;
}
using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId);
foreach (var etoItem in eventData.Entity.PaymentItems) var payment = await _paymentRepository.FindAsync(eventData.Entity.Id);
if (payment == null)
{
return;
}
if (eventData.Entity.CompletionTime.HasValue && !payment.CompletionTime.HasValue)
{
_unitOfWorkManager.Current.OnCompleted(async () =>
{ {
var item = payment.PaymentItems.FirstOrDefault(i => i.Id == etoItem.Id); await _distributedEventBus.PublishAsync(new EShopPaymentCompletedEto
if (item == null)
{ {
if (!Guid.TryParse(etoItem.GetProperty<string>("StoreId"), out var storeId)) Payment = _objectMapper.Map<Payment, EShopPaymentEto>(payment)
{ });
throw new StoreIdNotFoundException(); });
} }
item = _objectMapper.Map<PaymentItemEto, PaymentItem>(etoItem);
item.SetStoreId(storeId);
payment.PaymentItems.Add(item);
}
else
{
_objectMapper.Map(etoItem, item);
}
}
var etoPaymentItemIds = eventData.Entity.PaymentItems.Select(i => i.Id).ToList(); _objectMapper.Map(eventData.Entity, payment);
payment.PaymentItems.RemoveAll(i => !etoPaymentItemIds.Contains(i.Id)); foreach (var etoItem in eventData.Entity.PaymentItems)
{
var item = payment.PaymentItems.FirstOrDefault(i => i.Id == etoItem.Id);
if (item == null)
{
item = _objectMapper.Map<PaymentItemEto, PaymentItem>(etoItem);
FillPaymentItemStoreId(item);
payment.PaymentItems.Add(item);
}
else
{
_objectMapper.Map(etoItem, item);
}
} }
var etoPaymentItemIds = eventData.Entity.PaymentItems.Select(i => i.Id).ToList();
payment.PaymentItems.RemoveAll(i => !etoPaymentItemIds.Contains(i.Id));
await _paymentRepository.UpdateAsync(payment, true); await _paymentRepository.UpdateAsync(payment, true);
} }
protected virtual void FillPaymentItemStoreId(PaymentItem item)
{
if (!Guid.TryParse(item.GetProperty<string>("StoreId"), out var storeId))
{
throw new StoreIdNotFoundException();
}
item.SetStoreId(storeId);
}
[UnitOfWork(true)]
public virtual async Task HandleEventAsync(EntityDeletedEto<PaymentEto> eventData) public virtual async Task HandleEventAsync(EntityDeletedEto<PaymentEto> eventData)
{ {
using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId);
var payment = await _paymentRepository.FindAsync(eventData.Entity.Id); var payment = await _paymentRepository.FindAsync(eventData.Entity.Id);
if (payment == null) if (payment == null)

3
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain/EasyAbp/EShop/Payments/PaymentsDomainAutoMapperProfile.cs

@ -25,6 +25,9 @@ namespace EasyAbp.EShop.Payments
CreateMap<RefundItemEto, RefundItem>(MemberList.Source) CreateMap<RefundItemEto, RefundItem>(MemberList.Source)
.Ignore(x => x.StoreId) .Ignore(x => x.StoreId)
.Ignore(x => x.OrderId); .Ignore(x => x.OrderId);
CreateMap<Payment, EShopPaymentEto>();
CreateMap<PaymentItem, EShopPaymentItemEto>();
CreateMap<Refund, OrderRefundEto>(); CreateMap<Refund, OrderRefundEto>();
CreateMap<RefundItem, OrderRefundItemEto>(); CreateMap<RefundItem, OrderRefundItemEto>();
CreateMap<RefundItemOrderLine, RefundItemOrderLineEto>(); CreateMap<RefundItemOrderLine, RefundItemOrderLineEto>();

133
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Domain/EasyAbp/EShop/Payments/Refunds/RefundSynchronizer.cs

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.EShop.Payments.Payments;
using EasyAbp.PaymentService.Refunds; using EasyAbp.PaymentService.Refunds;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -16,6 +17,7 @@ using Volo.Abp.Uow;
namespace EasyAbp.EShop.Payments.Refunds namespace EasyAbp.EShop.Payments.Refunds
{ {
public class RefundSynchronizer : public class RefundSynchronizer :
IDistributedEventHandler<EntityCreatedEto<RefundEto>>,
IDistributedEventHandler<EntityUpdatedEto<RefundEto>>, IDistributedEventHandler<EntityUpdatedEto<RefundEto>>,
IDistributedEventHandler<EntityDeletedEto<RefundEto>>, IDistributedEventHandler<EntityDeletedEto<RefundEto>>,
IRefundSynchronizer, IRefundSynchronizer,
@ -27,6 +29,7 @@ namespace EasyAbp.EShop.Payments.Refunds
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IDistributedEventBus _distributedEventBus; private readonly IDistributedEventBus _distributedEventBus;
private readonly IPaymentRepository _paymentRepository;
private readonly IRefundRepository _refundRepository; private readonly IRefundRepository _refundRepository;
public RefundSynchronizer( public RefundSynchronizer(
@ -36,6 +39,7 @@ namespace EasyAbp.EShop.Payments.Refunds
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IUnitOfWorkManager unitOfWorkManager, IUnitOfWorkManager unitOfWorkManager,
IDistributedEventBus distributedEventBus, IDistributedEventBus distributedEventBus,
IPaymentRepository paymentRepository,
IRefundRepository refundRepository) IRefundRepository refundRepository)
{ {
_objectMapper = objectMapper; _objectMapper = objectMapper;
@ -44,71 +48,103 @@ namespace EasyAbp.EShop.Payments.Refunds
_jsonSerializer = jsonSerializer; _jsonSerializer = jsonSerializer;
_unitOfWorkManager = unitOfWorkManager; _unitOfWorkManager = unitOfWorkManager;
_distributedEventBus = distributedEventBus; _distributedEventBus = distributedEventBus;
_paymentRepository = paymentRepository;
_refundRepository = refundRepository; _refundRepository = refundRepository;
} }
[UnitOfWork(true)]
public virtual async Task HandleEventAsync(EntityCreatedEto<RefundEto> eventData)
{
using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId);
var refund = await _refundRepository.FindAsync(eventData.Entity.Id);
if (refund != null)
{
return;
}
var payment = await _paymentRepository.FindAsync(eventData.Entity.PaymentId);
if (payment == null)
{
return;
}
refund = _objectMapper.Map<RefundEto, Refund>(eventData.Entity);
refund.SetRefundItems(
_objectMapper.Map<List<RefundItemEto>, List<RefundItem>>(eventData.Entity.RefundItems));
refund.RefundItems.ForEach(item =>
{
FillRefundItemStoreId(item);
FillRefundItemOrderId(item);
});
FillRefundItemOrderLines(refund);
await _refundRepository.InsertAsync(refund, true);
if (refund.CompletedTime.HasValue)
{
_unitOfWorkManager.Current.OnCompleted(async () =>
await _distributedEventBus.PublishAsync(new OrderRefundCompletedEto
{Refund = _objectMapper.Map<Refund, OrderRefundEto>(refund)}));
}
}
[UnitOfWork(true)] [UnitOfWork(true)]
public virtual async Task HandleEventAsync(EntityUpdatedEto<RefundEto> eventData) public virtual async Task HandleEventAsync(EntityUpdatedEto<RefundEto> eventData)
{ {
using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId); using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId);
var publishOrderRefundCompletedEvent = false;
var refund = await _refundRepository.FindAsync(eventData.Entity.Id); var refund = await _refundRepository.FindAsync(eventData.Entity.Id);
if (refund == null) if (refund == null)
{ {
refund = _objectMapper.Map<RefundEto, Refund>(eventData.Entity); return;
}
refund.SetRefundItems(
_objectMapper.Map<List<RefundItemEto>, List<RefundItem>>(eventData.Entity.RefundItems));
refund.RefundItems.ForEach(item => if (eventData.Entity.CompletedTime.HasValue && !refund.CompletedTime.HasValue)
{ {
FillRefundItemStoreId(item); _unitOfWorkManager.Current.OnCompleted(async () =>
FillRefundItemOrderId(item); await _distributedEventBus.PublishAsync(new OrderRefundCompletedEto
}); {Refund = _objectMapper.Map<Refund, OrderRefundEto>(refund)}));
}
if (refund.CompletedTime.HasValue) _objectMapper.Map(eventData.Entity, refund);
foreach (var etoItem in eventData.Entity.RefundItems)
{
var item = refund.RefundItems.FirstOrDefault(i => i.Id == etoItem.Id);
if (item == null)
{ {
publishOrderRefundCompletedEvent = true; item = _objectMapper.Map<RefundItemEto, RefundItem>(etoItem);
refund.RefundItems.Add(item);
} }
else
await _refundRepository.InsertAsync(refund, true);
}
else
{
if (eventData.Entity.CompletedTime.HasValue && !refund.CompletedTime.HasValue)
{ {
publishOrderRefundCompletedEvent = true; _objectMapper.Map(etoItem, item);
} }
FillRefundItemStoreId(item);
FillRefundItemOrderId(item);
}
_objectMapper.Map(eventData.Entity, refund); var etoRefundItemIds = eventData.Entity.RefundItems.Select(i => i.Id).ToList();
foreach (var etoItem in eventData.Entity.RefundItems) refund.RefundItems.RemoveAll(i => !etoRefundItemIds.Contains(i.Id));
{
var item = refund.RefundItems.FirstOrDefault(i => i.Id == etoItem.Id);
if (item == null) FillRefundItemOrderLines(refund);
{
item = _objectMapper.Map<RefundItemEto, RefundItem>(etoItem);
refund.RefundItems.Add(item);
}
else
{
_objectMapper.Map(etoItem, item);
}
FillRefundItemStoreId(item); await _refundRepository.UpdateAsync(refund, true);
FillRefundItemOrderId(item); }
}
var etoRefundItemIds = eventData.Entity.RefundItems.Select(i => i.Id).ToList();
refund.RefundItems.RemoveAll(i => !etoRefundItemIds.Contains(i.Id));
}
protected virtual void FillRefundItemOrderLines(Refund refund)
{
foreach (var refundItem in refund.RefundItems) foreach (var refundItem in refund.RefundItems)
{ {
var orderLineInfoModels = var orderLineInfoModels =
@ -135,16 +171,6 @@ namespace EasyAbp.EShop.Payments.Refunds
refundItem.RefundItemOrderLines.RemoveAll(i => !orderLineIds.Contains(i.OrderLineId)); refundItem.RefundItemOrderLines.RemoveAll(i => !orderLineIds.Contains(i.OrderLineId));
} }
} }
await _refundRepository.UpdateAsync(refund, true);
var orderRefundEto = _objectMapper.Map<Refund, OrderRefundEto>(refund);
if (publishOrderRefundCompletedEvent)
{
_unitOfWorkManager.Current.OnCompleted(async () =>
await _distributedEventBus.PublishAsync(new OrderRefundCompletedEto {Refund = orderRefundEto}));
}
} }
protected virtual void FillRefundItemStoreId(RefundItem item) protected virtual void FillRefundItemStoreId(RefundItem item)
@ -167,8 +193,11 @@ namespace EasyAbp.EShop.Payments.Refunds
item.SetOrderId(orderId); item.SetOrderId(orderId);
} }
[UnitOfWork(true)]
public virtual async Task HandleEventAsync(EntityDeletedEto<RefundEto> eventData) public virtual async Task HandleEventAsync(EntityDeletedEto<RefundEto> eventData)
{ {
using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId);
var refund = await _refundRepository.FindAsync(eventData.Entity.Id); var refund = await _refundRepository.FindAsync(eventData.Entity.Id);
if (refund == null) if (refund == null)

6
modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.EntityFrameworkCore/EasyAbp/EShop/Payments/Refunds/RefundRepository.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using EasyAbp.EShop.Payments.EntityFrameworkCore; using EasyAbp.EShop.Payments.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
@ -12,6 +13,11 @@ namespace EasyAbp.EShop.Payments.Refunds
{ {
} }
public override IQueryable<Refund> WithDetails()
{
return base.WithDetails().Include(x => x.RefundItems);
}
public IQueryable<Refund> GetQueryableByUserId(Guid userId) public IQueryable<Refund> GetQueryableByUserId(Guid userId)
{ {
return from refund in DbContext.Refunds return from refund in DbContext.Refunds

7
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderCreatedEventHandler.cs

@ -32,12 +32,11 @@ namespace EasyAbp.EShop.Products.Products
_productManager = productManager; _productManager = productManager;
} }
[UnitOfWork(true)]
public virtual async Task HandleEventAsync(EntityCreatedEto<OrderEto> eventData) public virtual async Task HandleEventAsync(EntityCreatedEto<OrderEto> eventData)
{ {
using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId); using var changeTenant = _currentTenant.Change(eventData.Entity.TenantId);
using var uow = _unitOfWorkManager.Begin(isTransactional: true);
var models = new List<ConsumeInventoryModel>(); var models = new List<ConsumeInventoryModel>();
foreach (var orderLine in eventData.Entity.OrderLines) foreach (var orderLine in eventData.Entity.OrderLines)
@ -84,14 +83,14 @@ namespace EasyAbp.EShop.Products.Products
continue; continue;
} }
await uow.RollbackAsync(); await _unitOfWorkManager.Current.RollbackAsync();
await PublishResultEventAsync(eventData, false); await PublishResultEventAsync(eventData, false);
return; return;
} }
await uow.CompleteAsync(); await _unitOfWorkManager.Current.CompleteAsync();
await PublishResultEventAsync(eventData, true); await PublishResultEventAsync(eventData, true);
} }

7
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderPaidEventHandler.cs

@ -31,12 +31,11 @@ namespace EasyAbp.EShop.Products.Products
_productManager = productManager; _productManager = productManager;
} }
[UnitOfWork(true)]
public virtual async Task HandleEventAsync(OrderPaidEto eventData) public virtual async Task HandleEventAsync(OrderPaidEto eventData)
{ {
using var changeTenant = _currentTenant.Change(eventData.Order.TenantId); using var changeTenant = _currentTenant.Change(eventData.Order.TenantId);
using var uow = _unitOfWorkManager.Begin(isTransactional: true);
var models = new List<ConsumeInventoryModel>(); var models = new List<ConsumeInventoryModel>();
foreach (var orderLine in eventData.Order.OrderLines) foreach (var orderLine in eventData.Order.OrderLines)
@ -83,14 +82,14 @@ namespace EasyAbp.EShop.Products.Products
continue; continue;
} }
await uow.RollbackAsync(); await _unitOfWorkManager.Current.RollbackAsync();
await PublishResultEventAsync(eventData, false); await PublishResultEventAsync(eventData, false);
return; return;
} }
await uow.CompleteAsync(); await _unitOfWorkManager.Current.CompleteAsync();
await PublishResultEventAsync(eventData, true); await PublishResultEventAsync(eventData, true);
} }

Loading…
Cancel
Save