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"> |
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
<ConfigureAwait /> |
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
</Weavers> |
</Weavers> |
||||
Loading…
Reference in new issue