mirror of https://github.com/EasyAbp/EShop.git
37 changed files with 746 additions and 4 deletions
@ -0,0 +1,38 @@ |
|||
# EShop.Plugins.Booking |
|||
|
|||
[](https://abp.io) |
|||
[](https://www.nuget.org/packages/EasyAbp.EShop.Plugins.Booking.Domain.Shared) |
|||
[](https://www.nuget.org/packages/EasyAbp.EShop.Plugins.Booking.Domain.Shared) |
|||
[](https://discord.gg/S6QaezrCRq) |
|||
[](https://www.github.com/EasyAbp/EShop) |
|||
|
|||
A booking-business plugin for EShop. It extends EShop to use the [EasyAbp.BookingService](https://github.com/EasyAbp/BookingService) module to help end-users to book some assets online. |
|||
|
|||
## Installation |
|||
|
|||
1. Install the following NuGet packages. ([see how](https://github.com/EasyAbp/EasyAbpGuide/blob/master/docs/How-To.md#add-nuget-packages)) |
|||
|
|||
* EasyAbp.EShop.Orders.Plugins.Booking (install at EasyAbp.EShop.Orders.Application location) |
|||
* (Optional) EasyAbp.EShop.Payments.Plugins.Booking (install at EasyAbp.EShop.Payments.Application location) |
|||
* EasyAbp.EShop.Plugins.Booking.Application |
|||
* EasyAbp.EShop.Plugins.Booking.Application |
|||
* EasyAbp.EShop.Plugins.Booking.Application.Contracts |
|||
* EasyAbp.EShop.Plugins.Booking.Domain |
|||
* EasyAbp.EShop.Plugins.Booking.Domain.Shared |
|||
* EasyAbp.EShop.Plugins.Booking.EntityFrameworkCore |
|||
* EasyAbp.EShop.Plugins.Booking.HttpApi |
|||
* EasyAbp.EShop.Plugins.Booking.HttpApi.Client |
|||
* (Optional) EasyAbp.EShop.Plugins.Booking.MongoDB |
|||
* (Optional) EasyAbp.EShop.Plugins.Booking.Web |
|||
|
|||
> Skip installing the `EasyAbp.EShop.Payments.Plugins.Booking` module if you don't want to check assets are bookable during payment. |
|||
|
|||
1. Add `DependsOn(typeof(EShopXxxModule))` attribute to configure the module dependencies. ([see how](https://github.com/EasyAbp/EasyAbpGuide/blob/master/docs/How-To.md#add-module-dependencies)) |
|||
|
|||
1. Add `builder.ConfigureEShopPluginsBooking();` to the `OnModelCreating()` method in **MyProjectMigrationsDbContext.cs**. |
|||
|
|||
1. Add EF Core migrations and update your database. See: [ABP document](https://docs.abp.io/en/abp/latest/Tutorials/Part-1?UI=MVC&DB=EF#add-database-migration). |
|||
|
|||
## Usage |
|||
|
|||
[](https://mermaid-js.github.io/mermaid-live-editor/edit#pako:eNqtlMtOwzAQRX_F8gaQQtlHqBItWVOo2GXj2pPWqmMHP5Ciqv_OJHbb0BcgkU0Sz9zjO_bYG8qNAJpTBx8BNIdnyZaW1aUm-Lw7sPfjcTFfmWb0YgVYl5OpBeaBMLIwZi31kpguEAXDzCPhaKbCUmo3mkRZTgrtggXiVwhzDvyDlzUQ6XowWyg4y-w85aT_Jby3Is6YnbG2Bu3R7twz69FtE0dIZWw_5YnrneS_fF_wMzV1o8BHfTJ1wUYsNQ0QnoTiF6bzGE7R3ZSi8ObKPp0U2sdnTB7rjhIRkL7mYD8lB1RyHpo2Lo97XNjx7SSodRx96gaReBeR36VXzHRipnlLLLig_J7a8_bRtz54wDPlB1IXOAfMT2t4uaCjlh_u2aBxQDkY0Csm1Z_RqAR1AHdlMS2wyCrga98kqUdAiytH8zWAbUndRtSNI84zH9yP56hBLJrLDj2WIYLw3hsImtEabI2NgBfFpqOVFI3VUNIcPwVUDNe8pKXeYmpoBB7KQkhvLM0rhmuUURa8mbea09zbALukdNmkrO0XWziVvA) |
|||
@ -0,0 +1 @@ |
|||
/docs/plugins/booking/README.md |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\modules\EasyAbp.EShop.Orders\src\EasyAbp.EShop.Orders.Application\EasyAbp.EShop.Orders.Application.csproj" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Orders.Plugins.Booking.Shared\EasyAbp.EShop.Orders.Plugins.Booking.Shared.csproj" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Plugins.Booking.Application.Contracts\EasyAbp.EShop.Plugins.Booking.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,56 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using EasyAbp.EShop.Plugins.Booking.BookingProductGroupDefinitions; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Booking.Authorization |
|||
{ |
|||
public class BookingOrderCreationAuthorizationHandler : OrderCreationAuthorizationHandler |
|||
{ |
|||
private readonly IBookingProductGroupDefinitionAppService _definitionAppService; |
|||
|
|||
public BookingOrderCreationAuthorizationHandler( |
|||
IBookingProductGroupDefinitionAppService definitionAppService) |
|||
{ |
|||
_definitionAppService = definitionAppService; |
|||
} |
|||
|
|||
protected override async Task HandleOrderCreationAsync(AuthorizationHandlerContext context, |
|||
OrderOperationAuthorizationRequirement requirement, OrderCreationResource resource) |
|||
{ |
|||
var productGroupNames = (await _definitionAppService.GetListAsync()).Items.Select(x => x.ProductGroupName); |
|||
|
|||
var bookingOrderLines = resource.Input.OrderLines.Where(x => |
|||
productGroupNames.Contains(resource.ProductDictionary[x.ProductId].ProductGroupName)).ToList(); |
|||
|
|||
if (!bookingOrderLines.Any()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
foreach (var orderLine in bookingOrderLines) |
|||
{ |
|||
var assetId = orderLine.FindBookingAssetId(); |
|||
if (assetId is not null) |
|||
{ |
|||
// Todo: Invoke IProductAssetAppService to check the mapping.
|
|||
} |
|||
else |
|||
{ |
|||
var assetCategoryId = orderLine.FindBookingAssetCategoryId(); |
|||
if (assetCategoryId is null) |
|||
{ |
|||
context.Fail(); |
|||
return; |
|||
} |
|||
// Todo: Invoke IProductAssetCategoryAppService to check the mapping.
|
|||
} |
|||
|
|||
// Todo: Invoke IAssetOccupancyAppService to check the booking info.
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
namespace EasyAbp.EShop.Orders.Plugins.Booking; |
|||
|
|||
public class BookingOrderConsts |
|||
{ |
|||
public static string BookingOrderAutoCancellationResult = "Asset occupancy failed"; |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using EasyAbp.EShop.Orders.Plugins.Booking.ObjectExtending; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Booking |
|||
{ |
|||
[DependsOn( |
|||
typeof(EShopOrdersApplicationModule), |
|||
typeof(EShopOrdersApplicationContractsModule) |
|||
)] |
|||
public class EShopOrdersPluginsBookingModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
EShopOrdersPluginsBookingObjectExtensions.Configure(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.BookingService.AssetOccupancies; |
|||
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.Orders.Plugins.Booking.EventHandlers; |
|||
|
|||
public class BulkAssetOccupancyResultEventHandler : IDistributedEventHandler<BulkAssetOccupancyResultEto>, ITransientDependency |
|||
{ |
|||
private readonly IOrderManager _orderManager; |
|||
private readonly IOrderRepository _orderRepository; |
|||
|
|||
public BulkAssetOccupancyResultEventHandler( |
|||
IOrderManager orderManager, |
|||
IOrderRepository orderRepository) |
|||
{ |
|||
_orderManager = orderManager; |
|||
_orderRepository = orderRepository; |
|||
} |
|||
|
|||
[UnitOfWork(true)] |
|||
public virtual async Task HandleEventAsync(BulkAssetOccupancyResultEto eventData) |
|||
{ |
|||
var orderId = eventData.FindBookingOrderId(); |
|||
|
|||
if (orderId is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var order = await _orderRepository.GetAsync(orderId.Value); |
|||
|
|||
if (eventData.Success) |
|||
{ |
|||
if (order.CompletionTime.HasValue) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await _orderManager.CompleteAsync(order); |
|||
} |
|||
else |
|||
{ |
|||
if (order.CanceledTime.HasValue) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await _orderManager.CancelAsync(order, BookingOrderConsts.BookingOrderAutoCancellationResult); |
|||
|
|||
await RefundOrderAsync(order); |
|||
} |
|||
} |
|||
|
|||
protected virtual async Task RefundOrderAsync(Order order) |
|||
{ |
|||
// Todo: create a RefundOrderPaymentEto event to refund the order's payment.
|
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using EasyAbp.EShop.Orders.Orders.Dtos; |
|||
using EasyAbp.EShop.Plugins.Booking; |
|||
using Volo.Abp.ObjectExtending; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Booking.ObjectExtending |
|||
{ |
|||
public static class EShopOrdersPluginsBookingObjectExtensions |
|||
{ |
|||
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); |
|||
|
|||
public static void Configure() |
|||
{ |
|||
OneTimeRunner.Run(() => |
|||
{ |
|||
/* You can configure extension properties to entities or other object types |
|||
* defined in the depended modules. |
|||
* |
|||
* If you are using EF Core and want to map the entity extension properties to new |
|||
* table fields in the database, then configure them in the EShopSampleEfCoreEntityExtensionMappings |
|||
* |
|||
* Example: |
|||
* |
|||
* ObjectExtensionManager.Instance |
|||
* .AddOrUpdateProperty<IdentityRole, string>("Title"); |
|||
* |
|||
* See the documentation for more: |
|||
* https://docs.abp.io/en/abp/latest/Object-Extensions
|
|||
*/ |
|||
|
|||
ObjectExtensionManager.Instance |
|||
.AddOrUpdate( |
|||
new[] |
|||
{ |
|||
typeof(OrderLine), |
|||
typeof(OrderLineDto), |
|||
typeof(OrderLineEto), |
|||
typeof(CreateOrderLineDto) |
|||
}, |
|||
config => |
|||
{ |
|||
config.AddOrUpdateProperty<Guid?>(BookingOrderProperties.OrderLineBookingAssetId); |
|||
config.AddOrUpdateProperty<Guid?>(BookingOrderProperties.OrderLineBookingAssetCategoryId); |
|||
config.AddOrUpdateProperty<DateTime?>(BookingOrderProperties.OrderLineBookingDate); |
|||
config.AddOrUpdateProperty<TimeSpan?>(BookingOrderProperties.OrderLineBookingStartingTime); |
|||
config.AddOrUpdateProperty<TimeSpan?>(BookingOrderProperties.OrderLineBookingDuration); |
|||
} |
|||
) |
|||
.AddOrUpdate( |
|||
new[] |
|||
{ |
|||
typeof(OrderLine), |
|||
typeof(OrderLineDto), |
|||
typeof(OrderLineEto) |
|||
}, |
|||
config => |
|||
{ |
|||
config.AddOrUpdateProperty<Guid?>(BookingOrderProperties.OrderLineBookingAssetOccupancyId); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\modules\EasyAbp.EShop.Payments\src\EasyAbp.EShop.Payments.Application\EasyAbp.EShop.Payments.Application.csproj" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Orders.Plugins.Booking.Shared\EasyAbp.EShop.Orders.Plugins.Booking.Shared.csproj" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Plugins.Booking.Application.Contracts\EasyAbp.EShop.Plugins.Booking.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,36 @@ |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Orders; |
|||
using EasyAbp.EShop.Payments.Payments; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
|
|||
namespace EasyAbp.EShop.Payments.Plugins.Booking.Authorization |
|||
{ |
|||
public class BookingPaymentCreationAuthorizationHandler : PaymentCreationAuthorizationHandler |
|||
{ |
|||
public BookingPaymentCreationAuthorizationHandler() |
|||
{ |
|||
} |
|||
|
|||
protected override async Task HandlePaymentCreationAsync(AuthorizationHandlerContext context, |
|||
PaymentOperationAuthorizationRequirement requirement, PaymentCreationResource resource) |
|||
{ |
|||
foreach (var order in resource.Orders) |
|||
{ |
|||
foreach (var orderLine in order.OrderLines) |
|||
{ |
|||
var assetId = orderLine.FindBookingAssetId(); |
|||
if (assetId is null) |
|||
{ |
|||
var assetCategoryId = orderLine.FindBookingAssetCategoryId(); |
|||
if (assetCategoryId is null) |
|||
{ |
|||
continue; |
|||
} |
|||
} |
|||
|
|||
// Todo: Invoke IAssetOccupancyAppService to check the booking info.
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using EasyAbp.EShop.Plugins.Booking; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace EasyAbp.EShop.Payments.Plugins.Booking |
|||
{ |
|||
[DependsOn( |
|||
typeof(EShopPaymentsApplicationModule), |
|||
typeof(EShopPluginsBookingApplicationContractsModule) |
|||
)] |
|||
public class EShopPaymentsPluginsBookingModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,12 @@ |
|||
using System; |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace EasyAbp.BookingService.AssetOccupancies; |
|||
|
|||
public static class BulkAssetOccupancyResultEtoExtensions |
|||
{ |
|||
public static Guid? FindBookingOrderId(this BulkAssetOccupancyResultEto eto) |
|||
{ |
|||
return eto.GetProperty<Guid?>(BulkAssetOccupancyResultEtoProperties.BookingOrderId); |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
namespace EasyAbp.BookingService.AssetOccupancies; |
|||
|
|||
public class BulkAssetOccupancyResultEtoProperties |
|||
{ |
|||
public const string BookingOrderId = "BookingOrderId"; |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace EasyAbp.BookingService.AssetOccupancies; |
|||
|
|||
public static class BulkOccupyAssetEtoExtensions |
|||
{ |
|||
public static Guid? FindBookingOrderId(this BulkOccupyAssetEto eto) |
|||
{ |
|||
return eto.GetProperty<Guid?>(BulkOccupyAssetEtoProperties.BookingOrderId); |
|||
} |
|||
|
|||
public static void SetBookingOrderId(this BulkOccupyAssetEto eto, Guid? value) |
|||
{ |
|||
eto.SetProperty(BulkOccupyAssetEtoProperties.BookingOrderId, value); |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
namespace EasyAbp.BookingService.AssetOccupancies; |
|||
|
|||
public class BulkOccupyAssetEtoProperties |
|||
{ |
|||
public const string BookingOrderId = "BookingOrderId"; |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
namespace EasyAbp.EShop.Orders; |
|||
|
|||
public class BookingOrderProperties |
|||
{ |
|||
public const string OrderLineBookingAssetId = "BookingAssetId"; |
|||
|
|||
public const string OrderLineBookingAssetCategoryId = "BookingAssetCategoryId"; |
|||
|
|||
public const string OrderLineBookingDate = "BookingDate"; |
|||
|
|||
public const string OrderLineBookingStartingTime = "BookingStartingTime"; |
|||
|
|||
public const string OrderLineBookingDuration = "BookingDuration"; |
|||
|
|||
public const string OrderLineBookingAssetOccupancyId = "BookingAssetOccupancyId"; |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Orders.Orders.Dtos; |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace EasyAbp.EShop.Orders; |
|||
|
|||
public static class CreateOrderLineDtoExtensions |
|||
{ |
|||
public static Guid? FindBookingAssetId(this CreateOrderLineDto orderLine) |
|||
{ |
|||
return orderLine.GetProperty<Guid?>(BookingOrderProperties.OrderLineBookingAssetId); |
|||
} |
|||
|
|||
public static Guid? FindBookingAssetCategoryId(this CreateOrderLineDto orderLine) |
|||
{ |
|||
return orderLine.GetProperty<Guid?>(BookingOrderProperties.OrderLineBookingAssetCategoryId); |
|||
} |
|||
|
|||
public static DateTime? FindBookingDate(this CreateOrderLineDto orderLine) |
|||
{ |
|||
return orderLine.GetProperty<DateTime?>(BookingOrderProperties.OrderLineBookingDate); |
|||
} |
|||
|
|||
public static TimeSpan? FindBookingStartingTime(this CreateOrderLineDto orderLine) |
|||
{ |
|||
return orderLine.GetProperty<TimeSpan?>(BookingOrderProperties.OrderLineBookingStartingTime); |
|||
} |
|||
|
|||
public static TimeSpan? FindBookingDuration(this CreateOrderLineDto orderLine) |
|||
{ |
|||
return orderLine.GetProperty<TimeSpan?>(BookingOrderProperties.OrderLineBookingDuration); |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace EasyAbp.EShop.Orders; |
|||
|
|||
public static class OrderLineExtensions |
|||
{ |
|||
public static Guid? FindBookingAssetId(this IOrderLine orderLine) |
|||
{ |
|||
return orderLine.GetProperty<Guid?>(BookingOrderProperties.OrderLineBookingAssetId); |
|||
} |
|||
|
|||
public static Guid? FindBookingAssetCategoryId(this IOrderLine orderLine) |
|||
{ |
|||
return orderLine.GetProperty<Guid?>(BookingOrderProperties.OrderLineBookingAssetCategoryId); |
|||
} |
|||
|
|||
public static DateTime? FindBookingDate(this IOrderLine orderLine) |
|||
{ |
|||
return orderLine.GetProperty<DateTime?>(BookingOrderProperties.OrderLineBookingDate); |
|||
} |
|||
|
|||
public static TimeSpan? FindBookingStartingTime(this IOrderLine orderLine) |
|||
{ |
|||
return orderLine.GetProperty<TimeSpan?>(BookingOrderProperties.OrderLineBookingStartingTime); |
|||
} |
|||
|
|||
public static TimeSpan? FindBookingDuration(this IOrderLine orderLine) |
|||
{ |
|||
return orderLine.GetProperty<TimeSpan?>(BookingOrderProperties.OrderLineBookingDuration); |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Booking.BookingProductGroupDefinitions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class BookingProductGroupDefinitionDto |
|||
{ |
|||
public string ProductGroupName { get; set; } |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Booking.BookingProductGroupDefinitions.Dtos; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Booking.BookingProductGroupDefinitions; |
|||
|
|||
public interface IBookingProductGroupDefinitionAppService : IApplicationService |
|||
{ |
|||
Task<ListResultDto<BookingProductGroupDefinitionDto>> GetListAsync(); |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Booking.BookingProductGroupDefinitions.Dtos; |
|||
using EasyAbp.EShop.Plugins.Booking.Options; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Booking.BookingProductGroupDefinitions; |
|||
|
|||
public class BookingProductGroupDefinitionAppService : BookingAppService, IBookingProductGroupDefinitionAppService |
|||
{ |
|||
private readonly EShopBookingOptions _options; |
|||
|
|||
public BookingProductGroupDefinitionAppService(IOptions<EShopBookingOptions> options) |
|||
{ |
|||
_options = options.Value; |
|||
} |
|||
|
|||
public virtual Task<ListResultDto<BookingProductGroupDefinitionDto>> GetListAsync() |
|||
{ |
|||
return Task.FromResult( |
|||
new ListResultDto<BookingProductGroupDefinitionDto>( |
|||
_options.BookingProductGroups.Select(x => |
|||
new BookingProductGroupDefinitionDto |
|||
{ |
|||
ProductGroupName = x.ProductGroupName |
|||
}).ToList() |
|||
) |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.BookingService.AssetOccupancies; |
|||
using EasyAbp.EShop.Orders; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Booking.EventHandlers; |
|||
|
|||
public class BookingOrderPaidEventHandler : IDistributedEventHandler<OrderPaidEto>, ITransientDependency |
|||
{ |
|||
private readonly IDistributedEventBus _distributedEventBus; |
|||
|
|||
public BookingOrderPaidEventHandler(IDistributedEventBus distributedEventBus) |
|||
{ |
|||
_distributedEventBus = distributedEventBus; |
|||
} |
|||
|
|||
public virtual async Task HandleEventAsync(OrderPaidEto eventData) |
|||
{ |
|||
var occupyModels = new List<OccupyAssetInfoModel>(); |
|||
var occupyByCategoryModels = new List<OccupyAssetByCategoryInfoModel>(); |
|||
|
|||
foreach (var orderLine in eventData.Order.OrderLines) |
|||
{ |
|||
var assetId = orderLine.FindBookingAssetId(); |
|||
var assetCategoryId = orderLine.FindBookingAssetCategoryId(); |
|||
var date = orderLine.FindBookingDate(); |
|||
var startingTime = orderLine.FindBookingStartingTime(); |
|||
var duration = orderLine.FindBookingDuration(); |
|||
|
|||
if (date is null || startingTime is null || duration is null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (assetId.HasValue) |
|||
{ |
|||
occupyModels.Add(new OccupyAssetInfoModel( |
|||
assetId: assetId.Value, |
|||
date: date.Value, |
|||
startingTime: startingTime.Value, |
|||
duration: duration.Value, |
|||
occupierUserId: eventData.Order.CustomerUserId |
|||
)); |
|||
} |
|||
else if (assetCategoryId.HasValue) |
|||
{ |
|||
occupyByCategoryModels.Add(new OccupyAssetByCategoryInfoModel( |
|||
assetCategoryId: assetCategoryId.Value, |
|||
date: date.Value, |
|||
startingTime: startingTime.Value, |
|||
duration: duration.Value, |
|||
occupierUserId: eventData.Order.CustomerUserId |
|||
)); |
|||
} |
|||
} |
|||
|
|||
var eto = new BulkOccupyAssetEto(eventData.TenantId, occupyModels, occupyByCategoryModels); |
|||
|
|||
eto.SetBookingOrderId(eventData.Order.Id); |
|||
|
|||
await _distributedEventBus.PublishAsync(eto); |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Booking.Options; |
|||
|
|||
public class BookingProductGroupDefinition |
|||
{ |
|||
[NotNull] |
|||
public string ProductGroupName { get; set; } |
|||
|
|||
public BookingProductGroupDefinition([NotNull] string productGroupName) |
|||
{ |
|||
ProductGroupName = productGroupName; |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Booking.Options; |
|||
|
|||
public class EShopBookingOptions |
|||
{ |
|||
/// <summary>
|
|||
/// Which product groups are for booking business.
|
|||
/// </summary>
|
|||
public List<BookingProductGroupDefinition> BookingProductGroups { get; } = new(); |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System; |
|||
using Volo.Abp.Domain.Entities.Auditing; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Booking.ProductAssetCategories; |
|||
|
|||
/// <summary>
|
|||
/// Mapping of ProductSku to AssetCategory.
|
|||
/// Set which SKU can use to book a specified asset category.
|
|||
/// </summary>
|
|||
public class ProductAssetCategory : AuditedAggregateRoot<Guid>, IMultiTenant |
|||
{ |
|||
public virtual Guid? TenantId { get; protected set; } |
|||
|
|||
public virtual Guid ProductId { get; protected set; } |
|||
|
|||
public virtual Guid ProductSkuId { get; protected set; } |
|||
|
|||
public virtual Guid AssetCategoryId { get; protected set; } |
|||
|
|||
/// <summary>
|
|||
/// Fall back to the price of ProductSku if <c>null</c>.
|
|||
/// </summary>
|
|||
public virtual decimal? Price { get; protected set; } |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System; |
|||
using Volo.Abp.Domain.Entities.Auditing; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Booking.ProductAssets; |
|||
|
|||
/// <summary>
|
|||
/// Mapping of ProductSku to Asset.
|
|||
/// Set which SKU can use to book a specified asset.
|
|||
/// </summary>
|
|||
public class ProductAsset : AuditedAggregateRoot<Guid>, IMultiTenant |
|||
{ |
|||
public virtual Guid? TenantId { get; protected set; } |
|||
|
|||
public virtual Guid ProductId { get; protected set; } |
|||
|
|||
public virtual Guid ProductSkuId { get; protected set; } |
|||
|
|||
public virtual Guid AssetId { get; protected set; } |
|||
|
|||
/// <summary>
|
|||
/// Fall back to the price of ProductSku if <c>null</c>.
|
|||
/// </summary>
|
|||
public virtual decimal? Price { get; protected set; } |
|||
} |
|||
@ -1,3 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait /> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
Loading…
Reference in new issue