mirror of https://github.com/EasyAbp/EShop.git
81 changed files with 5470 additions and 474 deletions
@ -0,0 +1,12 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Products.Products.Dtos; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Orders |
|||
{ |
|||
public interface IOrderDiscountProvider |
|||
{ |
|||
Task<Order> DiscountAsync(Order order, Dictionary<Guid, ProductDto> productDict); |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Orders |
|||
{ |
|||
public class DiscountAmountOverflowException : BusinessException |
|||
{ |
|||
public DiscountAmountOverflowException() |
|||
: base("DiscountAmountOverflow", $"The discount amount overflow.") |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,10 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Orders |
|||
{ |
|||
public interface IOrderDiscountProvider |
|||
{ |
|||
Task<Order> DiscountAsync(Order order); |
|||
} |
|||
} |
|||
@ -1,100 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using EasyAbp.EShop.Orders.Orders.Dtos; |
|||
using EasyAbp.EShop.Plugins.Coupons; |
|||
using EasyAbp.EShop.Plugins.Coupons.Coupons; |
|||
using EasyAbp.EShop.Plugins.Coupons.CouponTemplates; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Timing; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Coupons.Authorization |
|||
{ |
|||
public class CouponOrderCreationAuthorizationHandler : OrderCreationAuthorizationHandler |
|||
{ |
|||
private readonly IClock _clock; |
|||
private readonly ICouponLookupService _couponLookupService; |
|||
private readonly ICouponTemplateLookupService _couponTemplateLookupService; |
|||
|
|||
public CouponOrderCreationAuthorizationHandler( |
|||
IClock clock, |
|||
ICouponLookupService couponLookupService, |
|||
ICouponTemplateLookupService couponTemplateLookupService) |
|||
{ |
|||
_clock = clock; |
|||
_couponLookupService = couponLookupService; |
|||
_couponTemplateLookupService = couponTemplateLookupService; |
|||
} |
|||
|
|||
protected override async Task HandleOrderCreationAsync(AuthorizationHandlerContext context, |
|||
OrderOperationAuthorizationRequirement requirement, OrderCreationResource resource) |
|||
{ |
|||
if (!Guid.TryParse(resource.Input.GetProperty<string>(CouponsConsts.OrderCouponIdPropertyName), |
|||
out var couponId)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var now = _clock.Now; |
|||
|
|||
var coupon = await _couponLookupService.FindByIdAsync(couponId); |
|||
|
|||
if (coupon == null || coupon.ExpirationTime < now) |
|||
{ |
|||
context.Fail(); |
|||
return; |
|||
} |
|||
|
|||
var couponTemplate = await _couponTemplateLookupService.FindByIdAsync(coupon.CouponTemplateId); |
|||
|
|||
if (couponTemplate == null || |
|||
!IsInUsableTime(couponTemplate, now) || |
|||
!IsOrderInScope(couponTemplate, resource)) |
|||
{ |
|||
context.Fail(); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
protected virtual bool IsOrderInScope(CouponTemplateData couponTemplate, OrderCreationResource resource) |
|||
{ |
|||
if (couponTemplate.IsUnscoped) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
var expectedOrderLines = new List<CreateOrderLineDto>(); |
|||
|
|||
foreach (var scope in couponTemplate.Scopes) |
|||
{ |
|||
expectedOrderLines.AddRange(resource.Input.OrderLines |
|||
.WhereIf(scope.ProductGroupName != null, |
|||
x => resource.ProductDictionary[x.ProductId].ProductGroupName == scope.ProductGroupName) |
|||
.WhereIf(scope.ProductId.HasValue, x => x.ProductId == scope.ProductId) |
|||
.WhereIf(scope.ProductSkuId.HasValue, x => x.ProductSkuId == scope.ProductSkuId)); |
|||
} |
|||
|
|||
if (couponTemplate.IsCrossProductAllowed) |
|||
{ |
|||
return expectedOrderLines.Sum(x => GetOrderLineProductPrice(x, resource) * x.Quantity) >= |
|||
couponTemplate.ConditionAmount; |
|||
} |
|||
|
|||
return expectedOrderLines.Any(orderLine => |
|||
GetOrderLineProductPrice(orderLine, resource) >= couponTemplate.ConditionAmount); |
|||
} |
|||
|
|||
protected virtual decimal GetOrderLineProductPrice(CreateOrderLineDto createOrderLineDto, OrderCreationResource resource) |
|||
{ |
|||
return resource.ProductDictionary[createOrderLineDto.ProductId].GetSkuById(createOrderLineDto.ProductSkuId).Price; |
|||
} |
|||
|
|||
protected virtual bool IsInUsableTime(ICouponTemplate couponTemplate, DateTime now) |
|||
{ |
|||
return couponTemplate.UsableBeginTime <= now && couponTemplate.UsableEndTime > now; |
|||
} |
|||
} |
|||
} |
|||
@ -1,23 +1,18 @@ |
|||
using EasyAbp.EShop.Orders.Plugins.Coupons.Authorization; |
|||
using EasyAbp.EShop.Orders.Plugins.Coupons.ObjectExtending; |
|||
using EasyAbp.EShop.Orders.Plugins.Coupons.ObjectExtending; |
|||
using EasyAbp.EShop.Plugins.Coupons; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Coupons |
|||
{ |
|||
[DependsOn( |
|||
typeof(EShopOrdersDomainModule), |
|||
typeof(EShopPluginsCouponsDomainSharedModule) |
|||
typeof(EShopPluginsCouponsApplicationContractsModule) |
|||
)] |
|||
public class EShopOrdersPluginsCouponsModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
EShopOrdersPluginsCouponsObjectExtensions.Configure(); |
|||
|
|||
context.Services.AddSingleton<IAuthorizationHandler, CouponOrderCreationAuthorizationHandler>(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,12 @@ |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Coupons.OrderDiscount |
|||
{ |
|||
public class CouponNotFoundOrHasExpiredException : BusinessException |
|||
{ |
|||
public CouponNotFoundOrHasExpiredException() : base("CouponNotFoundOrHasExpired", |
|||
"Coupon not found or has expired.") |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Coupons.OrderDiscount |
|||
{ |
|||
public class CouponTemplateNotFoundOrUnavailableException : BusinessException |
|||
{ |
|||
public CouponTemplateNotFoundOrUnavailableException() : base("CouponTemplateNotFoundOrUnavailable", |
|||
"Coupon template not found or unavailable.") |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Coupons.OrderDiscount |
|||
{ |
|||
public class OrderDoesNotMeetCouponUsageConditionException : BusinessException |
|||
{ |
|||
public OrderDoesNotMeetCouponUsageConditionException() : base("OrderDoesNotMeetCouponUsageCondition", |
|||
"Order does not meet the coupon usage condition.") |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Coupons |
|||
{ |
|||
public class CouponHasBeenOccupiedException : BusinessException |
|||
{ |
|||
public CouponHasBeenOccupiedException() : base("CouponHasBeenOccupied", "Coupon has been occupied.") |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Coupons.Dtos |
|||
{ |
|||
[Serializable] |
|||
public class GetCouponListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
public bool AvailableOnly { get; set; } |
|||
|
|||
public Guid? UserId { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Coupons.Dtos |
|||
{ |
|||
[Serializable] |
|||
public class OccupyCouponInput |
|||
{ |
|||
public Guid OrderId { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System; |
|||
namespace EasyAbp.EShop.Plugins.Coupons.Coupons.Dtos |
|||
{ |
|||
[Serializable] |
|||
public class UpdateCouponDto |
|||
{ |
|||
public DateTime? ExpirationTime { get; set; } |
|||
} |
|||
} |
|||
@ -1,39 +1,41 @@ |
|||
{ |
|||
"culture": "pl-PL", |
|||
"texts": { |
|||
"Permission:CouponTemplate": "CouponTemplate", |
|||
"Permission:CouponTemplate": "Coupon template", |
|||
"Permission:Create": "Create", |
|||
"Permission:Update": "Update", |
|||
"Permission:Delete": "Delete", |
|||
"Menu:CouponTemplate": "MenuCouponTemplate", |
|||
"CouponTemplate": "CouponTemplate", |
|||
"CouponTemplateStoreId": "CouponTemplateStoreId", |
|||
"CouponTemplateCouponType": "CouponTemplateCouponType", |
|||
"CouponTemplateUniqueName": "CouponTemplateUniqueName", |
|||
"CouponTemplateDisplayName": "CouponTemplateDisplayName", |
|||
"CouponTemplateDescription": "CouponTemplateDescription", |
|||
"CouponTemplateUsableDuration": "CouponTemplateUsableDuration", |
|||
"CouponTemplateUsableBeginTime": "CouponTemplateUsableBeginTime", |
|||
"CouponTemplateUsableEndTime": "CouponTemplateUsableEndTime", |
|||
"CouponTemplateConditionAmount": "CouponTemplateConditionAmount", |
|||
"CouponTemplateDiscountAmount": "CouponTemplateDiscountAmount", |
|||
"CouponTemplateIsCrossProductAllowed": "CouponTemplateIsCrossProductAllowed", |
|||
"CouponTemplateIsUnscoped": "CouponTemplateIsUnscoped", |
|||
"CreateCouponTemplate": "CreateCouponTemplate", |
|||
"EditCouponTemplate": "EditCouponTemplate", |
|||
"CouponTemplateDeletionConfirmationMessage": "Are you sure to delete the couponTemplate {0}?", |
|||
"Menu:CouponTemplate": "Coupon template", |
|||
"CouponTemplate": "Coupon template", |
|||
"CouponTemplateStoreId": "Store ID", |
|||
"CouponTemplateCouponType": "Coupon type", |
|||
"CouponTemplateUniqueName": "Unique name", |
|||
"CouponTemplateDisplayName": "Display name", |
|||
"CouponTemplateDescription": "Description", |
|||
"CouponTemplateUsableDuration": "Usable duration", |
|||
"CouponTemplateUsableBeginTime": "Usable begin time", |
|||
"CouponTemplateUsableEndTime": "Usable end time", |
|||
"CouponTemplateConditionAmount": "Condition amount", |
|||
"CouponTemplateDiscountAmount": "Discount amount", |
|||
"CouponTemplateIsUnscoped": "Unscoped", |
|||
"CreateCouponTemplate": "New", |
|||
"EditCouponTemplate": "Edit", |
|||
"CouponTemplateDeletionConfirmationMessage": "Are you sure to delete the coupon template {0}?", |
|||
"SuccessfullyDeleted": "Successfully deleted", |
|||
"CouponType.Normal": "X discount", |
|||
"CouponType.PerMeet": "X discount for every Y", |
|||
"CouponType.Custom": "Custom", |
|||
"Permission:Coupon": "Coupon", |
|||
"Menu:Coupon": "MenuCoupon", |
|||
"Menu:Coupon": "Coupon", |
|||
"Coupon": "Coupon", |
|||
"CouponCouponTemplateId": "CouponCouponTemplateId", |
|||
"CouponUserId": "CouponUserId", |
|||
"CouponOrderId": "CouponOrderId", |
|||
"CouponExpirationTime": "CouponExpirationTime", |
|||
"CouponUsedTime": "CouponUsedTime", |
|||
"CouponDiscountedAmount": "CouponDiscountedAmount", |
|||
"CreateCoupon": "CreateCoupon", |
|||
"EditCoupon": "EditCoupon", |
|||
"CouponCouponTemplateId": "Coupon template ID", |
|||
"CouponUserId": "User ID", |
|||
"CouponOrderId": "Order ID", |
|||
"CouponExpirationTime": "Expiration time", |
|||
"CouponUsedTime": "Used time", |
|||
"CouponDiscountedAmount": "Discounted amount", |
|||
"CreateCoupon": "New", |
|||
"EditCoupon": "Edit", |
|||
"CouponDeletionConfirmationMessage": "Are you sure to delete the coupon {0}?" |
|||
} |
|||
} |
|||
@ -1,39 +1,41 @@ |
|||
{ |
|||
"culture": "pt-BR", |
|||
"texts": { |
|||
"Permission:CouponTemplate": "CouponTemplate", |
|||
"Permission:CouponTemplate": "Coupon template", |
|||
"Permission:Create": "Create", |
|||
"Permission:Update": "Update", |
|||
"Permission:Delete": "Delete", |
|||
"Menu:CouponTemplate": "MenuCouponTemplate", |
|||
"CouponTemplate": "CouponTemplate", |
|||
"CouponTemplateStoreId": "CouponTemplateStoreId", |
|||
"CouponTemplateCouponType": "CouponTemplateCouponType", |
|||
"CouponTemplateUniqueName": "CouponTemplateUniqueName", |
|||
"CouponTemplateDisplayName": "CouponTemplateDisplayName", |
|||
"CouponTemplateDescription": "CouponTemplateDescription", |
|||
"CouponTemplateUsableDuration": "CouponTemplateUsableDuration", |
|||
"CouponTemplateUsableBeginTime": "CouponTemplateUsableBeginTime", |
|||
"CouponTemplateUsableEndTime": "CouponTemplateUsableEndTime", |
|||
"CouponTemplateConditionAmount": "CouponTemplateConditionAmount", |
|||
"CouponTemplateDiscountAmount": "CouponTemplateDiscountAmount", |
|||
"CouponTemplateIsCrossProductAllowed": "CouponTemplateIsCrossProductAllowed", |
|||
"CouponTemplateIsUnscoped": "CouponTemplateIsUnscoped", |
|||
"CreateCouponTemplate": "CreateCouponTemplate", |
|||
"EditCouponTemplate": "EditCouponTemplate", |
|||
"CouponTemplateDeletionConfirmationMessage": "Are you sure to delete the couponTemplate {0}?", |
|||
"Menu:CouponTemplate": "Coupon template", |
|||
"CouponTemplate": "Coupon template", |
|||
"CouponTemplateStoreId": "Store ID", |
|||
"CouponTemplateCouponType": "Coupon type", |
|||
"CouponTemplateUniqueName": "Unique name", |
|||
"CouponTemplateDisplayName": "Display name", |
|||
"CouponTemplateDescription": "Description", |
|||
"CouponTemplateUsableDuration": "Usable duration", |
|||
"CouponTemplateUsableBeginTime": "Usable begin time", |
|||
"CouponTemplateUsableEndTime": "Usable end time", |
|||
"CouponTemplateConditionAmount": "Condition amount", |
|||
"CouponTemplateDiscountAmount": "Discount amount", |
|||
"CouponTemplateIsUnscoped": "Unscoped", |
|||
"CreateCouponTemplate": "New", |
|||
"EditCouponTemplate": "Edit", |
|||
"CouponTemplateDeletionConfirmationMessage": "Are you sure to delete the coupon template {0}?", |
|||
"SuccessfullyDeleted": "Successfully deleted", |
|||
"CouponType.Normal": "X discount", |
|||
"CouponType.PerMeet": "X discount for every Y", |
|||
"CouponType.Custom": "Custom", |
|||
"Permission:Coupon": "Coupon", |
|||
"Menu:Coupon": "MenuCoupon", |
|||
"Menu:Coupon": "Coupon", |
|||
"Coupon": "Coupon", |
|||
"CouponCouponTemplateId": "CouponCouponTemplateId", |
|||
"CouponUserId": "CouponUserId", |
|||
"CouponOrderId": "CouponOrderId", |
|||
"CouponExpirationTime": "CouponExpirationTime", |
|||
"CouponUsedTime": "CouponUsedTime", |
|||
"CouponDiscountedAmount": "CouponDiscountedAmount", |
|||
"CreateCoupon": "CreateCoupon", |
|||
"EditCoupon": "EditCoupon", |
|||
"CouponCouponTemplateId": "Coupon template ID", |
|||
"CouponUserId": "User ID", |
|||
"CouponOrderId": "Order ID", |
|||
"CouponExpirationTime": "Expiration time", |
|||
"CouponUsedTime": "Used time", |
|||
"CouponDiscountedAmount": "Discounted amount", |
|||
"CreateCoupon": "New", |
|||
"EditCoupon": "Edit", |
|||
"CouponDeletionConfirmationMessage": "Are you sure to delete the coupon {0}?" |
|||
} |
|||
} |
|||
@ -1,39 +1,41 @@ |
|||
{ |
|||
"culture": "vi", |
|||
"texts": { |
|||
"Permission:CouponTemplate": "CouponTemplate", |
|||
"Permission:CouponTemplate": "Coupon template", |
|||
"Permission:Create": "Create", |
|||
"Permission:Update": "Update", |
|||
"Permission:Delete": "Delete", |
|||
"Menu:CouponTemplate": "MenuCouponTemplate", |
|||
"CouponTemplate": "CouponTemplate", |
|||
"CouponTemplateStoreId": "CouponTemplateStoreId", |
|||
"CouponTemplateCouponType": "CouponTemplateCouponType", |
|||
"CouponTemplateUniqueName": "CouponTemplateUniqueName", |
|||
"CouponTemplateDisplayName": "CouponTemplateDisplayName", |
|||
"CouponTemplateDescription": "CouponTemplateDescription", |
|||
"CouponTemplateUsableDuration": "CouponTemplateUsableDuration", |
|||
"CouponTemplateUsableBeginTime": "CouponTemplateUsableBeginTime", |
|||
"CouponTemplateUsableEndTime": "CouponTemplateUsableEndTime", |
|||
"CouponTemplateConditionAmount": "CouponTemplateConditionAmount", |
|||
"CouponTemplateDiscountAmount": "CouponTemplateDiscountAmount", |
|||
"CouponTemplateIsCrossProductAllowed": "CouponTemplateIsCrossProductAllowed", |
|||
"CouponTemplateIsUnscoped": "CouponTemplateIsUnscoped", |
|||
"CreateCouponTemplate": "CreateCouponTemplate", |
|||
"EditCouponTemplate": "EditCouponTemplate", |
|||
"CouponTemplateDeletionConfirmationMessage": "Are you sure to delete the couponTemplate {0}?", |
|||
"Menu:CouponTemplate": "Coupon template", |
|||
"CouponTemplate": "Coupon template", |
|||
"CouponTemplateStoreId": "Store ID", |
|||
"CouponTemplateCouponType": "Coupon type", |
|||
"CouponTemplateUniqueName": "Unique name", |
|||
"CouponTemplateDisplayName": "Display name", |
|||
"CouponTemplateDescription": "Description", |
|||
"CouponTemplateUsableDuration": "Usable duration", |
|||
"CouponTemplateUsableBeginTime": "Usable begin time", |
|||
"CouponTemplateUsableEndTime": "Usable end time", |
|||
"CouponTemplateConditionAmount": "Condition amount", |
|||
"CouponTemplateDiscountAmount": "Discount amount", |
|||
"CouponTemplateIsUnscoped": "Unscoped", |
|||
"CreateCouponTemplate": "New", |
|||
"EditCouponTemplate": "Edit", |
|||
"CouponTemplateDeletionConfirmationMessage": "Are you sure to delete the coupon template {0}?", |
|||
"SuccessfullyDeleted": "Successfully deleted", |
|||
"CouponType.Normal": "X discount", |
|||
"CouponType.PerMeet": "X discount for every Y", |
|||
"CouponType.Custom": "Custom", |
|||
"Permission:Coupon": "Coupon", |
|||
"Menu:Coupon": "MenuCoupon", |
|||
"Menu:Coupon": "Coupon", |
|||
"Coupon": "Coupon", |
|||
"CouponCouponTemplateId": "CouponCouponTemplateId", |
|||
"CouponUserId": "CouponUserId", |
|||
"CouponOrderId": "CouponOrderId", |
|||
"CouponExpirationTime": "CouponExpirationTime", |
|||
"CouponUsedTime": "CouponUsedTime", |
|||
"CouponDiscountedAmount": "CouponDiscountedAmount", |
|||
"CreateCoupon": "CreateCoupon", |
|||
"EditCoupon": "EditCoupon", |
|||
"CouponCouponTemplateId": "Coupon template ID", |
|||
"CouponUserId": "User ID", |
|||
"CouponOrderId": "Order ID", |
|||
"CouponExpirationTime": "Expiration time", |
|||
"CouponUsedTime": "Used time", |
|||
"CouponDiscountedAmount": "Discounted amount", |
|||
"CreateCoupon": "New", |
|||
"EditCoupon": "Edit", |
|||
"CouponDeletionConfirmationMessage": "Are you sure to delete the coupon {0}?" |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Coupons |
|||
{ |
|||
public class CouponOrderCanceledEventHandler : IDistributedEventHandler<OrderCanceledEto>, ITransientDependency |
|||
{ |
|||
private readonly ICouponRepository _couponRepository; |
|||
|
|||
public CouponOrderCanceledEventHandler(ICouponRepository couponRepository) |
|||
{ |
|||
_couponRepository = couponRepository; |
|||
} |
|||
|
|||
[UnitOfWork(true)] |
|||
public virtual async Task HandleEventAsync(OrderCanceledEto eventData) |
|||
{ |
|||
if (!Guid.TryParse(eventData.Order.GetProperty<string>(CouponsConsts.OrderCouponIdPropertyName), |
|||
out var couponId)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var coupon = await _couponRepository.GetAsync(couponId); |
|||
|
|||
coupon.SetOrderId(null); |
|||
coupon.SetUsed(null, null); |
|||
|
|||
await _couponRepository.UpdateAsync(coupon, true); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Entities.Events.Distributed; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
using Volo.Abp.Timing; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Coupons |
|||
{ |
|||
public class CouponOrderCreatedEventHandler : IDistributedEventHandler<EntityCreatedEto<OrderEto>>, ITransientDependency |
|||
{ |
|||
private readonly IClock _clock; |
|||
private readonly ICouponRepository _couponRepository; |
|||
|
|||
public CouponOrderCreatedEventHandler( |
|||
IClock clock, |
|||
ICouponRepository couponRepository) |
|||
{ |
|||
_clock = clock; |
|||
_couponRepository = couponRepository; |
|||
} |
|||
|
|||
[UnitOfWork(true)] |
|||
public virtual async Task HandleEventAsync(EntityCreatedEto<OrderEto> eventData) |
|||
{ |
|||
if (!Guid.TryParse(eventData.Entity.GetProperty<string>(CouponsConsts.OrderCouponIdPropertyName), |
|||
out var couponId)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var discountAmount = eventData.Entity.GetProperty<decimal>(CouponsConsts.OrderCouponDiscountAmountPropertyName); |
|||
|
|||
var coupon = await _couponRepository.GetAsync(couponId); |
|||
|
|||
if (coupon.OrderId != eventData.Entity.Id) |
|||
{ |
|||
throw new InvalidCouponOrderIdException(eventData.Entity.Id, coupon.OrderId); |
|||
} |
|||
|
|||
coupon.SetUsed(_clock.Now, discountAmount); |
|||
|
|||
await _couponRepository.UpdateAsync(coupon, true); |
|||
} |
|||
} |
|||
} |
|||
@ -1,9 +1,12 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Timing; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Coupons |
|||
{ |
|||
public interface ICouponRepository : IRepository<Coupon, Guid> |
|||
{ |
|||
IQueryable<Coupon> GetAvailableCouponQueryable(IClock clock); |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Coupons |
|||
{ |
|||
public class InvalidCouponOrderIdException : BusinessException |
|||
{ |
|||
public InvalidCouponOrderIdException(Guid expectedOrderId, Guid? actualOrderId) : base("InvalidCouponOrderId", |
|||
$"The expected order ID is {expectedOrderId}, but the actual order ID is {actualOrderId}.") |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,24 +1,29 @@ |
|||
using System; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Coupons.Coupons.Dtos; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.ObjectMapping; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Coupons |
|||
{ |
|||
[Dependency(TryRegister = true)] |
|||
public class HttpClientCouponLookupService : ICouponLookupService, ITransientDependency |
|||
{ |
|||
private readonly IObjectMapper _objectMapper; |
|||
private readonly ICouponAppService _couponAppService; |
|||
|
|||
public HttpClientCouponLookupService( |
|||
IObjectMapper objectMapper, |
|||
ICouponAppService couponAppService) |
|||
{ |
|||
_objectMapper = objectMapper; |
|||
_couponAppService = couponAppService; |
|||
} |
|||
|
|||
public virtual async Task<ICoupon> FindByIdAsync(Guid id, CancellationToken cancellationToken = default) |
|||
public virtual async Task<CouponData> FindByIdAsync(Guid id, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await _couponAppService.GetAsync(id); |
|||
return _objectMapper.Map<CouponDto, CouponData>(await _couponAppService.GetAsync(id)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,10 +1,9 @@ |
|||
using System; |
|||
|
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Web.Pages.EShop.Plugins.Coupons.Coupons.Coupon.ViewModels |
|||
{ |
|||
public class CreateEditCouponViewModel |
|||
public class CreateCouponViewModel |
|||
{ |
|||
[Display(Name = "CouponCouponTemplateId")] |
|||
public Guid CouponTemplateId { get; set; } |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Coupons.Web.Pages.EShop.Plugins.Coupons.Coupons.Coupon.ViewModels |
|||
{ |
|||
public class EditCouponViewModel |
|||
{ |
|||
[Display(Name = "CouponExpirationTime")] |
|||
public DateTime? ExpirationTime { get; set; } |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,24 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace EShopSample.Migrations |
|||
{ |
|||
public partial class RemovedIsCrossProductAllowed : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "IsCrossProductAllowed", |
|||
table: "EasyAbpEShopPluginsCouponsCouponTemplates"); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<bool>( |
|||
name: "IsCrossProductAllowed", |
|||
table: "EasyAbpEShopPluginsCouponsCouponTemplates", |
|||
type: "bit", |
|||
nullable: false, |
|||
defaultValue: false); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue