From 9ae75cd0b7ddef5f65c13dfd5d8a0fbec00df39e Mon Sep 17 00:00:00 2001 From: Jadyn Date: Mon, 27 Jun 2022 01:44:42 +0800 Subject: [PATCH] Implement basic FlashSales --- plugins/FlashSales/.editorconfig | 223 +++++++++++ .../CreateFlashSalesOrderEventHandler.cs | 95 +++++ ...hSalesOrderCreationAuthorizationHandler.cs | 40 ++ ...sFlashSalesApplicationAutoMapperProfile.cs | 35 ++ ...rdersPluginsFlashSalesApplicationModule.cs | 25 ++ ...hopPluginsFlashSalesRemoteServiceConsts.cs | 2 +- .../FlashSalesPlans/Dtos/CreateOrderInput.cs | 9 + .../Dtos/FlashSalesPlanCreateDto.cs | 21 + .../FlashSalesPlans/Dtos/FlashSalesPlanDto.cs | 23 ++ .../Dtos/FlashSalesPlanGetListInput.cs | 20 + .../Dtos/FlashSalesPlanUpdateDto.cs | 21 + .../IFlashSalesPlanAppService.cs | 21 + .../Dtos/FlashSalesResultDto.cs | 19 + .../Dtos/FlashSalesResultGetListInput.cs | 17 + .../IFlashSalesResultAppService.cs | 14 + .../FlashSalesPermissionDefinitionProvider.cs | 11 +- .../Permissions/FlashSalesPermissions.cs | 19 +- ...Shop.Plugins.FlashSales.Application.csproj | 3 + ...EShopPluginsFlashSalesApplicationModule.cs | 22 +- .../FlashSalesApplicationAutoMapperProfile.cs | 41 +- .../FlashSalesPlanAppService.cs | 362 ++++++++++++++++++ .../FlashSalesPlanCacheInvalidator.cs | 18 + .../FlashSalesPlanCacheItem.cs | 9 + .../FlashSalesResultAppService.cs | 51 +++ ...op.Plugins.FlashSales.Domain.Shared.csproj | 4 + .../FlashSales/FlashSalesErrorCodes.cs | 13 + .../CreateFlashSalesOrderCompleteEto.cs | 25 ++ .../CreateFlashSalesOrderEto.cs | 32 ++ .../FlashSalesPlans/FlashSalesPlanEto.cs | 22 ++ .../FlashSalesProductAttributeEto.cs | 16 + .../FlashSalesProductAttributeOptionEto.cs | 13 + .../FlashSalesPlans/FlashSalesProductEto.cs | 39 ++ .../FlashSalesProductSkuEto.cs | 25 ++ .../FlashSalesPlans/ProductDetailEto.cs | 10 + .../FlashSalesResultStatus.cs | 12 + .../FlashSales/FullAuditedEntityEto.cs | 23 ++ .../Localization/FlashSalesResource.cs | 2 +- .../Plugins/FlashSales/Localization/en.json | 31 +- .../FlashSales/Localization/zh-Hans.json | 31 +- .../FlashSales/Localization/zh-Hant.json | 31 +- ...Abp.EShop.Plugins.FlashSales.Domain.csproj | 1 + ...luginsFlashSalesDomainAutoMapperProfile.cs | 16 + .../EShopPluginsFlashSalesDomainModule.cs | 22 +- .../FlashSales/FlashSalesDbProperties.cs | 4 +- ...ndTimeMustBeLaterThanBeginTimeException.cs | 12 + .../FlashSalesPlans/FlashSalesPlan.cs | 58 +++ .../FlashSalesPlans/FlashSalesPlanManager.cs | 44 +++ .../IFlashSalesPlanRepository.cs | 8 + ...eateFlashSalesOrderCompleteEventHandler.cs | 37 ++ .../FlashSalesResults/FlashSalesResult.cs | 49 +++ .../IFlashSalesResultRepository.cs | 9 + ...ginsFlashSalesEntityFrameworkCoreModule.cs | 9 +- .../FlashSalesDbContext.cs | 12 +- ...shSalesDbContextModelCreatingExtensions.cs | 29 +- .../IFlashSalesDbContext.cs | 11 +- .../EfCoreFlashSalesPlanRepository.cs | 21 + .../FlashSalesPlanEfCoreQuerableExtensions.cs | 18 + .../EfCoreFlashSalesResultRepository.cs | 20 + ...lashSalesResultEfCoreQuerableExtensions.cs | 16 + .../FlashSalesPlanController.cs | 71 ++++ .../FlashSalesResultController.cs | 33 ++ .../MongoFlashSalesPlanRepository.cs | 13 + .../MongoFlashSalesResultRepository.cs | 13 + .../EShopPluginsFlashSalesMongoDbModule.cs | 9 +- .../MongoDB/FlashSalesMongoDbContext.cs | 11 +- .../FlashSalesMongoDbContextExtensions.cs | 8 +- .../MongoDB/IFlashSalesMongoDbContext.cs | 11 +- ...opPluginsFlashSalesWebAutoMapperProfile.cs | 12 + .../EShopPluginsFlashSalesWebModule.cs | 2 +- ...asyAbp.EShop.Plugins.FlashSales.Web.csproj | 5 + .../Menus/FlashSalesMenuContributor.cs | 40 +- .../Menus/FlashSalesMenus.cs | 12 +- .../FlashSalesPlan/CreateModal.cshtml | 21 + .../FlashSalesPlan/CreateModal.cshtml.cs | 27 ++ .../FlashSalesPlan/EditModal.cshtml | 22 ++ .../FlashSalesPlan/EditModal.cshtml.cs | 38 ++ .../FlashSalesPlan/Index.cshtml | 50 +++ .../FlashSalesPlan/Index.cshtml.cs | 11 + .../CreateFlashSalesPlanViewModel.cs | 25 ++ .../ViewModels/EditFlashSalesPlanViewModel.cs | 33 ++ .../FlashSalesPlans/FlashSalesPlan/index.css | 0 .../FlashSalesPlans/FlashSalesPlan/index.js | 87 +++++ .../FlashSalesResult/Index.cshtml | 41 ++ .../FlashSalesResult/Index.cshtml.cs | 11 + .../FlashSalesResult/ViewModal.cshtml | 22 ++ .../FlashSalesResult/ViewModal.cshtml.cs | 31 ++ .../ViewFlashSalesResultViewModel.cs | 23 ++ .../FlashSalesResult/index.css | 0 .../FlashSalesResult/index.js | 62 +++ .../EShop/Plugins/FlashSales/Index.cshtml | 5 +- .../EShop/Plugins/FlashSales/Index.cshtml.cs | 2 +- .../Plugins/FlashSales/_ViewImports.cshtml | 0 92 files changed, 2524 insertions(+), 73 deletions(-) create mode 100644 plugins/FlashSales/.editorconfig create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/CreateFlashSalesOrderEventHandler.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/FlashSalesOrderCreationAuthorizationHandler.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopOrdersPluginsFlashSalesApplicationAutoMapperProfile.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/CreateOrderInput.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateDto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanDto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanGetListInput.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanUpdateDto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/IFlashSalesPlanAppService.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/Dtos/FlashSalesResultDto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/Dtos/FlashSalesResultGetListInput.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/IFlashSalesResultAppService.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanAppService.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanCacheInvalidator.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanCacheItem.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultAppService.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/CreateFlashSalesOrderCompleteEto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/CreateFlashSalesOrderEto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanEto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductAttributeEto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductAttributeOptionEto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductEto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductSkuEto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/ProductDetailEto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultStatus.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FullAuditedEntityEto.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesDomainAutoMapperProfile.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/EndTimeMustBeLaterThanBeginTimeException.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanManager.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/IFlashSalesPlanRepository.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/CreateFlashSalesOrderCompleteEventHandler.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/IFlashSalesResultRepository.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/EfCoreFlashSalesPlanRepository.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanEfCoreQuerableExtensions.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/EfCoreFlashSalesResultRepository.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultEfCoreQuerableExtensions.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.HttpApi/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanController.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.HttpApi/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultController.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/MongoFlashSalesPlanRepository.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/MongoFlashSalesResultRepository.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/CreateModal.cshtml create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/CreateModal.cshtml.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/EditModal.cshtml create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/EditModal.cshtml.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/Index.cshtml create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/Index.cshtml.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/CreateFlashSalesPlanViewModel.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/EditFlashSalesPlanViewModel.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/index.css create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/index.js create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/Index.cshtml create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/Index.cshtml.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModal.cshtml create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModal.cshtml.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModels/ViewFlashSalesResultViewModel.cs create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/index.css create mode 100644 plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/index.js rename plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/{EasyAbp => }/EShop/Plugins/FlashSales/Index.cshtml (73%) rename plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/{EasyAbp => }/EShop/Plugins/FlashSales/Index.cshtml.cs (50%) rename plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/{EasyAbp => }/EShop/Plugins/FlashSales/_ViewImports.cshtml (100%) diff --git a/plugins/FlashSales/.editorconfig b/plugins/FlashSales/.editorconfig new file mode 100644 index 00000000..2e55c103 --- /dev/null +++ b/plugins/FlashSales/.editorconfig @@ -0,0 +1,223 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = true +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = omit_if_default + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = 0 + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = false +dotnet_style_allow_statement_immediately_after_block_experimental = false + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = false + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = false +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = false +csharp_style_expression_bodied_methods = false +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = true + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true +csharp_style_prefer_parameter_null_checking = true + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async + +# Code-block preferences +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true +csharp_style_namespace_declarations = file_scoped +csharp_style_prefer_method_group_conversion = true + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:suggestion + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/CreateFlashSalesOrderEventHandler.cs b/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/CreateFlashSalesOrderEventHandler.cs new file mode 100644 index 00000000..2deefa73 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/CreateFlashSalesOrderEventHandler.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using EasyAbp.EShop.Orders.Orders.Dtos; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Products.ProductDetails.Dtos; +using EasyAbp.EShop.Products.Products.Dtos; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.ObjectMapping; +using Volo.Abp.Uow; + +namespace EasyAbp.EShop.Orders.Orders; + +public class CreateFlashSalesOrderEventHandler : IDistributedEventHandler, ITransientDependency +{ + protected INewOrderGenerator NewOrderGenerator { get; } + + protected IObjectMapper ObjectMapper { get; } + + protected IEnumerable OrderDiscountProviders { get; } + + protected IOrderRepository OrderRepository { get; } + + protected IDistributedEventBus DistributedEventBus { get; } + + public CreateFlashSalesOrderEventHandler( + INewOrderGenerator newOrderGenerator, + IObjectMapper objectMapper, + IEnumerable orderDiscountProviders, + IOrderRepository orderRepository, + IDistributedEventBus distributedEventBus) + { + NewOrderGenerator = newOrderGenerator; + ObjectMapper = objectMapper; + OrderDiscountProviders = orderDiscountProviders; + OrderRepository = orderRepository; + DistributedEventBus = distributedEventBus; + } + + [UnitOfWork(true)] + public virtual async Task HandleEventAsync(CreateFlashSalesOrderEto eventData) + { + //How to check product is available? + //How to reduce product stock? + + var input = new CreateOrderDto() + { + StoreId = eventData.StoreId, + CustomerRemark = eventData.CustomerRemark, + OrderLines = new List() + { + new CreateOrderLineDto() + { + ProductId = eventData.Plan.ProductId, + ProductSkuId = eventData.Plan.ProductSkuId, + Quantity = eventData.Quantity + } + } + }; + var productDict = new Dictionary() + { + {eventData.Product.Id, ObjectMapper.Map(eventData.Product)} + }; + var productDetailDict = new Dictionary() + { + {eventData.ProductDetail.Id, ObjectMapper.Map(eventData.ProductDetail)} + }; + + var order = await NewOrderGenerator.GenerateAsync(eventData.UserId, input, productDict, productDetailDict); + + await DiscountOrderAsync(order, productDict); + + await OrderRepository.InsertAsync(order, autoSave: true); + + await DistributedEventBus.PublishAsync(new CreateFlashSalesOrderCompleteEto() + { + TenantId = eventData.TenantId, + PlanId = eventData.PlanId, + OrderId = order.Id, + UserId = eventData.UserId, + StoreId = eventData.StoreId, + PendingResultId = eventData.PendingResultId, + Success = true + }); + } + + protected virtual async Task DiscountOrderAsync(Order order, Dictionary productDict) + { + foreach (var provider in OrderDiscountProviders) + { + await provider.DiscountAsync(order, productDict); + } + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/FlashSalesOrderCreationAuthorizationHandler.cs b/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/FlashSalesOrderCreationAuthorizationHandler.cs new file mode 100644 index 00000000..16750493 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/FlashSalesOrderCreationAuthorizationHandler.cs @@ -0,0 +1,40 @@ +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp.DependencyInjection; + +namespace EasyAbp.EShop.Orders.Orders; + +public class FlashSalesOrderCreationAuthorizationHandler : OrderCreationAuthorizationHandler +{ + protected IAbpLazyServiceProvider LazyServiceProvider { get; } + + public FlashSalesOrderCreationAuthorizationHandler(IAbpLazyServiceProvider lazyServiceProvider) + { + LazyServiceProvider = lazyServiceProvider; + } + + protected override async Task HandleOrderCreationAsync(AuthorizationHandlerContext context, + OrderOperationAuthorizationRequirement requirement, OrderCreationResource resource) + { + var flashSalesPlanAppService = LazyServiceProvider.LazyGetRequiredService(); + foreach (var orderLine in resource.Input.OrderLines) + { + var plans = await flashSalesPlanAppService.GetListAsync(new FlashSalesPlanGetListInput() + { + StoreId = resource.Input.StoreId, + ProductId = orderLine.ProductId, + ProductSkuId = orderLine.ProductSkuId, + OnlyShowPublished = true + }); + if (plans.Items.Count > 0) + { + context.Fail(); + return; + } + } + + context.Succeed(requirement); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopOrdersPluginsFlashSalesApplicationAutoMapperProfile.cs b/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopOrdersPluginsFlashSalesApplicationAutoMapperProfile.cs new file mode 100644 index 00000000..2c6dcb70 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopOrdersPluginsFlashSalesApplicationAutoMapperProfile.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System; +using AutoMapper; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Products.ProductDetails.Dtos; +using EasyAbp.EShop.Products.Products; +using EasyAbp.EShop.Products.Products.Dtos; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; + +namespace EasyAbp.EShop.Orders +{ + public class EShopOrdersPluginsFlashSalesApplicationAutoMapperProfile : Profile, ISingletonDependency + { + public EShopOrdersPluginsFlashSalesApplicationAutoMapperProfile(IJsonSerializer jsonSerializer) + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + CreateMap(MemberList.Source) + .ForSourceMember(x => x.TenantId, opt => opt.DoNotValidate()) + .MapExtraProperties(); + CreateMap(MemberList.Source) + .ForMember(x => x.AttributeOptionIds, opt => opt.Ignore()) + .AfterMap((src, dest) => dest.AttributeOptionIds = jsonSerializer.Deserialize>(src.SerializedAttributeOptionIds)) + .MapExtraProperties(); + CreateMap(MemberList.Source) + .MapExtraProperties(); + CreateMap(MemberList.Source) + .MapExtraProperties(); + CreateMap(MemberList.Source) + .MapExtraProperties(); + } + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopOrdersPluginsFlashSalesApplicationModule.cs b/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopOrdersPluginsFlashSalesApplicationModule.cs index 7dd104d1..a0ecf1f7 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopOrdersPluginsFlashSalesApplicationModule.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopOrdersPluginsFlashSalesApplicationModule.cs @@ -1,12 +1,37 @@ using EasyAbp.EShop.Orders; +using EasyAbp.EShop.Orders.Orders; +using EasyAbp.EShop.Products; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; namespace EasyAbp.EShop.Plugins.FlashSales; [DependsOn( typeof(EShopOrdersApplicationModule), + typeof(EShopProductsApplicationContractsModule), typeof(EShopPluginsFlashSalesApplicationContractsModule) )] public class EShopOrdersPluginsFlashSalesApplicationModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSingleton(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + Configure(options => + { + options.Configurators.Add(abpAutoMapperConfigurationContext => + { + var profile = abpAutoMapperConfigurationContext.ServiceProvider + .GetRequiredService(); + + abpAutoMapperConfigurationContext.MapperConfiguration.AddProfile(profile); + }); + }); + } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesRemoteServiceConsts.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesRemoteServiceConsts.cs index 262522a2..f00bae2e 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesRemoteServiceConsts.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesRemoteServiceConsts.cs @@ -4,5 +4,5 @@ public class EShopPluginsFlashSalesRemoteServiceConsts { public const string RemoteServiceName = "FlashSales"; - public const string ModuleName = "flashSales"; + public const string ModuleName = "flash-sales"; } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/CreateOrderInput.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/CreateOrderInput.cs new file mode 100644 index 00000000..b696292b --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/CreateOrderInput.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; + +public class CreateOrderInput : ExtensibleEntityDto +{ + public string CustomerRemark { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateDto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateDto.cs new file mode 100644 index 00000000..c3be88e7 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateDto.cs @@ -0,0 +1,21 @@ +using System; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Entities; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; + +[Serializable] +public class FlashSalesPlanCreateDto : ExtensibleEntityDto +{ + public Guid StoreId { get; set; } + + public DateTime BeginTime { get; set; } + + public DateTime EndTime { get; set; } + + public Guid ProductId { get; set; } + + public Guid ProductSkuId { get; set; } + + public bool IsPublished { get; set; } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanDto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanDto.cs new file mode 100644 index 00000000..d488fe6d --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanDto.cs @@ -0,0 +1,23 @@ +using System; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Entities; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; + +[Serializable] +public class FlashSalesPlanDto : ExtensibleFullAuditedEntityDto, IHasConcurrencyStamp +{ + public Guid StoreId { get; set; } + + public DateTime BeginTime { get; set; } + + public DateTime EndTime { get; set; } + + public Guid ProductId { get; set; } + + public Guid ProductSkuId { get; set; } + + public bool IsPublished { get; set; } + + public string ConcurrencyStamp { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanGetListInput.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanGetListInput.cs new file mode 100644 index 00000000..e1b4f1fe --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanGetListInput.cs @@ -0,0 +1,20 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; + +[Serializable] +public class FlashSalesPlanGetListInput : ExtensiblePagedAndSortedResultRequestDto +{ + public Guid? StoreId { get; set; } + + public Guid? ProductId { get; set; } + + public Guid? ProductSkuId { get; set; } + + public bool OnlyShowPublished { get; set; } + + public DateTime? Start { get; set; } + + public DateTime? End { get; set; } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanUpdateDto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanUpdateDto.cs new file mode 100644 index 00000000..868f0657 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanUpdateDto.cs @@ -0,0 +1,21 @@ +using System; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Entities; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; + +[Serializable] +public class FlashSalesPlanUpdateDto : ExtensibleEntityDto, IHasConcurrencyStamp +{ + public DateTime BeginTime { get; set; } + + public DateTime EndTime { get; set; } + + public Guid ProductId { get; set; } + + public Guid ProductSkuId { get; set; } + + public bool IsPublished { get; set; } + + public string ConcurrencyStamp { get; set; } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/IFlashSalesPlanAppService.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/IFlashSalesPlanAppService.cs new file mode 100644 index 00000000..0dcaafc6 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/IFlashSalesPlanAppService.cs @@ -0,0 +1,21 @@ +using System; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; +using Volo.Abp.Application.Services; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public interface IFlashSalesPlanAppService : + ICrudAppService< + FlashSalesPlanDto, + Guid, + FlashSalesPlanGetListInput, + FlashSalesPlanCreateDto, + FlashSalesPlanUpdateDto> +{ + Task PreOrderAsync(Guid id); + + Task CheckPreOrderAsync(Guid id); + + Task CreateOrderAsync(Guid id, CreateOrderInput input); +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/Dtos/FlashSalesResultDto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/Dtos/FlashSalesResultDto.cs new file mode 100644 index 00000000..8cd4cd9f --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/Dtos/FlashSalesResultDto.cs @@ -0,0 +1,19 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults.Dtos; + +public class FlashSalesResultDto : ExtensibleFullAuditedEntityDto +{ + public virtual Guid StoreId { get; set; } + + public virtual Guid PlanId { get; set; } + + public virtual FlashSalesResultStatus Status { get; set; } + + public virtual string Reason { get; set; } + + public virtual Guid UserId { get; set; } + + public virtual Guid? OrderId { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/Dtos/FlashSalesResultGetListInput.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/Dtos/FlashSalesResultGetListInput.cs new file mode 100644 index 00000000..4b063273 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/Dtos/FlashSalesResultGetListInput.cs @@ -0,0 +1,17 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults.Dtos; + +public class FlashSalesResultGetListInput : ExtensiblePagedAndSortedResultRequestDto +{ + public virtual Guid? StoreId { get; set; } + + public virtual Guid? PlanId { get; set; } + + public virtual FlashSalesResultStatus? Status { get; set; } + + public virtual Guid? UserId { get; set; } + + public virtual Guid? OrderId { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/IFlashSalesResultAppService.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/IFlashSalesResultAppService.cs new file mode 100644 index 00000000..0b9a013e --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/IFlashSalesResultAppService.cs @@ -0,0 +1,14 @@ +using System; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults.Dtos; +using Volo.Abp.Application.Services; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +public interface IFlashSalesResultAppService : + IReadOnlyAppService< + FlashSalesResultDto, + Guid, + FlashSalesResultGetListInput> +{ + +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/Permissions/FlashSalesPermissionDefinitionProvider.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/Permissions/FlashSalesPermissionDefinitionProvider.cs index 7f957669..49b3e55a 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/Permissions/FlashSalesPermissionDefinitionProvider.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/Permissions/FlashSalesPermissionDefinitionProvider.cs @@ -1,4 +1,4 @@ -using EasyAbp.EShop.Plugins.FlashSales.Localization; +using EasyAbp.EShop.Plugins.FlashSales.Localization; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Localization; @@ -9,6 +9,15 @@ public class FlashSalesPermissionDefinitionProvider : PermissionDefinitionProvid public override void Define(IPermissionDefinitionContext context) { var myGroup = context.AddGroup(FlashSalesPermissions.GroupName, L("Permission:FlashSales")); + + var flashSalesPlanPermission = myGroup.AddPermission(FlashSalesPermissions.FlashSalesPlan.Default, L("Permission:FlashSalesPlan")); + flashSalesPlanPermission.AddChild(FlashSalesPermissions.FlashSalesPlan.Manage, L("Permission:Manage")); + flashSalesPlanPermission.AddChild(FlashSalesPermissions.FlashSalesPlan.Create, L("Permission:Create")); + flashSalesPlanPermission.AddChild(FlashSalesPermissions.FlashSalesPlan.Update, L("Permission:Update")); + flashSalesPlanPermission.AddChild(FlashSalesPermissions.FlashSalesPlan.Delete, L("Permission:Delete")); + + var flashSalesResultPermission = myGroup.AddPermission(FlashSalesPermissions.FlashSalesResult.Default, L("Permission:FlashSalesResult")); + flashSalesResultPermission.AddChild(FlashSalesPermissions.FlashSalesResult.Manage, L("Permission:Manage")); } private static LocalizableString L(string name) diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/Permissions/FlashSalesPermissions.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/Permissions/FlashSalesPermissions.cs index 61f4f82d..0ccaa1a5 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/Permissions/FlashSalesPermissions.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/Permissions/FlashSalesPermissions.cs @@ -1,13 +1,28 @@ -using Volo.Abp.Reflection; +using Volo.Abp.Reflection; namespace EasyAbp.EShop.Plugins.FlashSales.Permissions; public class FlashSalesPermissions { - public const string GroupName = "FlashSales"; + public const string GroupName = "EasyAbp.EShop.Plugins.FlashSales"; public static string[] GetAll() { return ReflectionHelper.GetPublicConstantsRecursively(typeof(FlashSalesPermissions)); } + + public class FlashSalesPlan + { + public const string Default = GroupName + ".FlashSalesPlan"; + public const string Manage = Default + ".Manage"; + public const string Update = Default + ".Update"; + public const string Create = Default + ".Create"; + public const string Delete = Default + ".Delete"; + } + + public class FlashSalesResult + { + public const string Default = GroupName + ".FlashSalesResult"; + public const string Manage = Default + ".Manage"; + } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp.EShop.Plugins.FlashSales.Application.csproj b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp.EShop.Plugins.FlashSales.Application.csproj index dfe3604c..3b42dbb7 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp.EShop.Plugins.FlashSales.Application.csproj +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp.EShop.Plugins.FlashSales.Application.csproj @@ -9,7 +9,10 @@ + + + diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesApplicationModule.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesApplicationModule.cs index 403f6949..260175c9 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesApplicationModule.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesApplicationModule.cs @@ -1,15 +1,20 @@ -using Microsoft.Extensions.DependencyInjection; +using EasyAbp.EShop.Products; +using EasyAbp.EShop.Stores; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Application; using Volo.Abp.AutoMapper; +using Volo.Abp.Caching; using Volo.Abp.Modularity; -using Volo.Abp.Application; namespace EasyAbp.EShop.Plugins.FlashSales; - [DependsOn( + typeof(EShopProductsApplicationContractsModule), typeof(EShopPluginsFlashSalesDomainModule), typeof(EShopPluginsFlashSalesApplicationContractsModule), + typeof(EShopStoresApplicationSharedModule), typeof(AbpDddApplicationModule), - typeof(AbpAutoMapperModule) + typeof(AbpAutoMapperModule), + typeof(AbpCachingModule) )] public class EShopPluginsFlashSalesApplicationModule : AbpModule { @@ -18,7 +23,14 @@ public class EShopPluginsFlashSalesApplicationModule : AbpModule context.Services.AddAutoMapperObjectMapper(); Configure(options => { - options.AddMaps(validate: true); + options.Configurators.Add(abpAutoMapperConfigurationContext => + { + var profile = abpAutoMapperConfigurationContext.ServiceProvider + .GetRequiredService(); + + abpAutoMapperConfigurationContext.MapperConfiguration.AddProfile(profile); + }); }); + } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesApplicationAutoMapperProfile.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesApplicationAutoMapperProfile.cs index 68505ad8..a5bf39b1 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesApplicationAutoMapperProfile.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesApplicationAutoMapperProfile.cs @@ -1,13 +1,48 @@ -using AutoMapper; +using System.Linq; +using AutoMapper; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults.Dtos; +using EasyAbp.EShop.Products.ProductDetails.Dtos; +using EasyAbp.EShop.Products.Products.Dtos; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; namespace EasyAbp.EShop.Plugins.FlashSales; -public class FlashSalesApplicationAutoMapperProfile : Profile +public class FlashSalesApplicationAutoMapperProfile : Profile, ISingletonDependency { - public FlashSalesApplicationAutoMapperProfile() + public FlashSalesApplicationAutoMapperProfile(IJsonSerializer jsonSerializer) { /* You can configure your AutoMapper mapping configuration here. * Alternatively, you can split your mapping configurations * into multiple profile classes for a better organization. */ + CreateMap() + .MapExtraProperties(); + CreateMap() + .ForMember(x => x.TenantId, opt => opt.Ignore()) + .MapExtraProperties(); + CreateMap(MemberList.Source); + CreateMap(MemberList.Source); + CreateMap() + .MapExtraProperties(); + + CreateMap() + .MapExtraProperties(); + + CreateMap() + .ForMember(x => x.TenantId, opt => opt.Ignore()) + .MapExtraProperties(); + CreateMap() + .ForMember(x => x.SerializedAttributeOptionIds, opt => opt.Ignore()) + .AfterMap((src, dest) => dest.SerializedAttributeOptionIds = jsonSerializer.Serialize(src.AttributeOptionIds.OrderBy(x => x))) + .MapExtraProperties(); + CreateMap() + .MapExtraProperties(); + CreateMap() + .MapExtraProperties(); + CreateMap() + .MapExtraProperties(); } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanAppService.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanAppService.cs new file mode 100644 index 00000000..67e8ddeb --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanAppService.cs @@ -0,0 +1,362 @@ +using System; +using System.Linq; +using System.Numerics; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using EasyAbp.EShop.Plugins.FlashSales.Permissions; +using EasyAbp.EShop.Products.ProductDetails; +using EasyAbp.EShop.Products.ProductDetails.Dtos; +using EasyAbp.EShop.Products.Products; +using EasyAbp.EShop.Products.Products.Dtos; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Caching.Distributed; +using Volo.Abp; +using Volo.Abp.Application.Services; +using Volo.Abp.Caching; +using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Users; +using static EasyAbp.EShop.Products.Permissions.ProductsPermissions; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +[Authorize] +public class FlashSalesPlanAppService : + CrudAppService, + IFlashSalesPlanAppService +{ + protected override string GetPolicyName { get; set; } + protected override string GetListPolicyName { get; set; } + protected override string CreatePolicyName { get; set; } = FlashSalesPermissions.FlashSalesPlan.Create; + protected override string UpdatePolicyName { get; set; } = FlashSalesPermissions.FlashSalesPlan.Update; + protected override string DeletePolicyName { get; set; } = FlashSalesPermissions.FlashSalesPlan.Delete; + + protected IFlashSalesPlanRepository FlashSalesPlanRepository { get; } + protected IProductAppService ProductAppService { get; } + protected IProductDetailAppService ProductDetailAppService { get; } + protected IDistributedCache TokenDistributedCache { get; } + protected IDistributedCache DistributedCache { get; } + protected IDistributedEventBus DistributedEventBus { get; } + protected FlashSalesPlanManager FlashSalesPlanManager { get; } + protected IFlashSalesResultRepository FlashSalesResultRepository { get; } + protected IAbpDistributedLock DistributedLock { get; } + + public FlashSalesPlanAppService( + IFlashSalesPlanRepository flashSalesPlanRepository, + IProductAppService productAppService, + IProductDetailAppService productDetailAppService, + IDistributedCache tokenDistributedCache, + IDistributedCache distributedCache, + IDistributedEventBus distributedEventBus, + FlashSalesPlanManager flashSalesPlanManager, + IFlashSalesResultRepository flashSalesResultRepository, + IAbpDistributedLock distributedLock) + : base(flashSalesPlanRepository) + { + FlashSalesPlanRepository = flashSalesPlanRepository; + ProductAppService = productAppService; + ProductDetailAppService = productDetailAppService; + TokenDistributedCache = tokenDistributedCache; + DistributedCache = distributedCache; + DistributedEventBus = distributedEventBus; + FlashSalesPlanManager = flashSalesPlanManager; + FlashSalesResultRepository = flashSalesResultRepository; + DistributedLock = distributedLock; + } + + public override async Task GetAsync(Guid id) + { + await CheckGetPolicyAsync(); + + var flashSalesPlan = await GetEntityByIdAsync(id); + + if (!flashSalesPlan.IsPublished) + { + await CheckPolicyAsync(FlashSalesPermissions.FlashSalesPlan.Manage); + } + + return await MapToGetOutputDtoAsync(flashSalesPlan); + } + + public override async Task CreateAsync(FlashSalesPlanCreateDto input) + { + await CheckCreatePolicyAsync(); + + var flashSalesPlan = await FlashSalesPlanManager.CreateAsync( + input.StoreId, + input.BeginTime, + input.EndTime, + input.ProductId, + input.ProductSkuId, + input.IsPublished + ); + + await FlashSalesPlanRepository.InsertAsync(flashSalesPlan, autoSave: true); + + return await MapToGetOutputDtoAsync(flashSalesPlan); + } + + public override async Task UpdateAsync(Guid id, FlashSalesPlanUpdateDto input) + { + await CheckUpdatePolicyAsync(); + + var flashSalesPlan = await GetEntityByIdAsync(id); + + await FlashSalesPlanManager.UpdateAsync( + flashSalesPlan, + input.BeginTime, + input.EndTime, + input.ProductId, + input.ProductSkuId, + input.IsPublished + ); + + flashSalesPlan.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); + + await FlashSalesPlanRepository.UpdateAsync(flashSalesPlan, autoSave: true); + + return await MapToGetOutputDtoAsync(flashSalesPlan); + } + + protected override async Task> CreateFilteredQueryAsync(FlashSalesPlanGetListInput input) + { + if (!input.OnlyShowPublished) + { + await CheckPolicyAsync(FlashSalesPermissions.FlashSalesPlan.Manage); + } + + return (await base.CreateFilteredQueryAsync(input)) + .WhereIf(input.StoreId.HasValue, x => x.StoreId == input.StoreId.Value) + .WhereIf(input.ProductId.HasValue, x => x.ProductId == input.ProductId.Value) + .WhereIf(input.ProductSkuId.HasValue, x => x.ProductSkuId == input.ProductSkuId.Value) + .WhereIf(input.OnlyShowPublished, x => x.IsPublished) + .WhereIf(input.Start.HasValue, x => x.BeginTime >= input.Start.Value) + .WhereIf(input.End.HasValue, x => x.BeginTime <= input.End.Value); + } + + public virtual async Task PreOrderAsync(Guid id) + { + var plan = await GetFlashSalesPlanCacheAsync(id); + var product = await ProductAppService.GetAsync(plan.ProductId); + var productSku = product.GetSkuById(plan.ProductSkuId); + + if (!product.IsPublished) + { + throw new BusinessException(FlashSalesErrorCodes.ProductIsNotPublished); + } + + if (product.InventoryStrategy != InventoryStrategy.FlashSales) + { + throw new BusinessException(FlashSalesErrorCodes.IsNotFlashSalesProduct); + } + + if (!plan.IsPublished) + { + throw new EntityNotFoundException(typeof(FlashSalesPlan), id); + } + + if (Clock.Now > plan.EndTime) + { + throw new BusinessException(FlashSalesErrorCodes.FlashSalesPlanIsExpired); + } + + await SetCacheHashTokenAsync(plan, product, productSku); + } + + public virtual async Task CheckPreOrderAsync(Guid id) + { + var plan = await GetFlashSalesPlanCacheAsync(id); + if (Clock.Now > plan.EndTime) + { + throw new BusinessException(FlashSalesErrorCodes.FlashSalesPlanIsExpired); + } + + var cacheHashToken = await GetCacheHashTokenAsync(plan); + if (cacheHashToken.IsNullOrWhiteSpace()) + { + throw new BusinessException(FlashSalesErrorCodes.PreOrderExipred); + } + + var product = await ProductAppService.GetAsync(plan.ProductId); + var productSku = product.GetSkuById(plan.ProductSkuId); + + if (!await ComparekHashTokenAsync(cacheHashToken, plan, product, productSku)) + { + throw new BusinessException(FlashSalesErrorCodes.PreOrderExipred); + } + } + + public virtual async Task CreateOrderAsync(Guid id, CreateOrderInput input) + { + var plan = await GetFlashSalesPlanCacheAsync(id); + var now = Clock.Now; + if (plan.BeginTime > now) + { + throw new BusinessException(FlashSalesErrorCodes.ProductIsNotPublished); + } + + if (now > plan.EndTime) + { + throw new BusinessException(FlashSalesErrorCodes.FlashSalesPlanIsExpired); + } + + var cacheHashToken = await GetCacheHashTokenAsync(plan); + if (cacheHashToken.IsNullOrWhiteSpace()) + { + throw new BusinessException(FlashSalesErrorCodes.PreOrderExipred); + } + + var product = await ProductAppService.GetAsync(plan.ProductId); + var productSku = product.GetSkuById(plan.ProductSkuId); + + if (!await ComparekHashTokenAsync(cacheHashToken, plan, product, productSku)) + { + throw new BusinessException(FlashSalesErrorCodes.PreOrderExipred); + } + + await RemoveCacheHashTokenAsync(plan); + + var userId = CurrentUser.GetId(); + + var result = await CreatePendingFlashSalesResultAsync(plan, userId); + + var CreateFlashSalesOrderEto = await PrepareCreateFlashSalesOrderEtoAsync(plan, product, productSku, result, input, userId, now); + + await DistributedEventBus.PublishAsync(CreateFlashSalesOrderEto); + } + + protected virtual async Task PrepareCreateFlashSalesOrderEtoAsync( + FlashSalesPlanDto plan, + ProductDto product, + ProductSkuDto productSku, + FlashSalesResult result, + CreateOrderInput input, + Guid userId, + DateTime now) + { + FlashSalesProductDetailEto productDetail = null; + var productDetailId = productSku.ProductDetailId ?? product.ProductDetailId; + if (productDetailId.HasValue) + { + productDetail = ObjectMapper.Map(await ProductDetailAppService.GetAsync(productDetailId.Value)); + } + var productEto = ObjectMapper.Map(product); + productEto.TenantId = CurrentTenant.Id; + var planEto = ObjectMapper.Map(plan); + planEto.TenantId = CurrentTenant.Id; + + var eto = new CreateFlashSalesOrderEto() + { + TenantId = CurrentTenant.Id, + PlanId = plan.Id, + UserId = userId, + PendingResultId = result.Id, + StoreId = plan.StoreId, + CreateTime = now, + CustomerRemark = input.CustomerRemark, + Quantity = 1,//should configure + Product = productEto, + ProductDetail = productDetail, + Plan = planEto + }; + + foreach (var item in input.ExtraProperties) + { + eto.ExtraProperties.Add(item.Key, item.Value); + } + + return eto; + } + + protected virtual async Task GetFlashSalesPlanCacheAsync(Guid id) + { + return await DistributedCache.GetOrAddAsync(id, async () => + { + var flashSalesPlan = await FlashSalesPlanRepository.GetAsync(id); + return ObjectMapper.Map(flashSalesPlan); + }); + } + + protected virtual Task GetCacheKeyAsync(FlashSalesPlanDto plan) + { + return Task.FromResult($"eshopflashsales_{CurrentUser.Id}_{plan.ProductSkuId}"); + } + + protected virtual async Task GetCacheHashTokenAsync(FlashSalesPlanDto plan) + { + return await TokenDistributedCache.GetStringAsync(await GetCacheKeyAsync(plan)); + } + + protected virtual async Task RemoveCacheHashTokenAsync(FlashSalesPlanDto plan) + { + await TokenDistributedCache.RemoveAsync(await GetCacheKeyAsync(plan)); + } + + protected virtual async Task SetCacheHashTokenAsync(FlashSalesPlanDto plan, ProductDto product, ProductSkuDto productSku) + { + await TokenDistributedCache.SetStringAsync(await GetCacheKeyAsync(plan), await GetHashTokenAsync(plan, product, productSku), new DistributedCacheEntryOptions() + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(3) + }); + } + + protected virtual Task GetHashTokenAsync(FlashSalesPlanDto plan, ProductDto product, ProductSkuDto productSku) + { + using var md5 = MD5.Create(); + var inputBytes = Encoding.UTF8.GetBytes($"{plan.LastModificationTime}|{product.LastModificationTime}|{productSku.LastModificationTime}"); + var sb = new StringBuilder(); + foreach (var t in md5.ComputeHash(inputBytes)) + { + sb.Append(t.ToString("X2")); + } + return Task.FromResult(sb.ToString()); + } + + protected virtual async Task ComparekHashTokenAsync(string cacheHashToken, FlashSalesPlanDto plan, ProductDto product, ProductSkuDto productSku) + { + if (cacheHashToken.IsNullOrWhiteSpace()) + { + return false; + } + + var hashToken = await GetHashTokenAsync(plan, product, productSku); + + return cacheHashToken == hashToken; + } + + protected virtual async Task CreatePendingFlashSalesResultAsync(FlashSalesPlanDto plan, Guid userId) + { + var lockKey = $"create-flash-sales-order-{plan.Id}-{userId}"; + + await using var handle = await DistributedLock.TryAcquireAsync(lockKey); + + if (handle == null) + { + throw new BusinessException(FlashSalesErrorCodes.CreateFlashSalesOrderBusy); + } + + // Prevent repeat submit + if (await FlashSalesResultRepository.AnyAsync(x => x.PlanId == plan.Id && x.UserId == userId)) + { + throw new BusinessException(FlashSalesErrorCodes.AlreadySubmitCreateFlashSalesOrder); + } + + var result = new FlashSalesResult( + id: GuidGenerator.Create(), + tenantId: CurrentTenant.Id, + storeId: plan.StoreId, + planId: plan.Id, + status: FlashSalesResultStatus.Pending, + reason: null, + userId: userId, + orderId: null + ); + return await FlashSalesResultRepository.InsertAsync(result, autoSave: true); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanCacheInvalidator.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanCacheInvalidator.cs new file mode 100644 index 00000000..7bc37dd3 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanCacheInvalidator.cs @@ -0,0 +1,18 @@ +using System; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; +using Volo.Abp.Caching; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.EventBus; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class FlashSalesPlanCacheInvalidator : ILocalEventHandler> +{ + protected IDistributedCache DistributedCache { get; } + + public virtual async Task HandleEventAsync(EntityChangedEventData eventData) + { + await DistributedCache.RemoveAsync(eventData.Entity.Id); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanCacheItem.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanCacheItem.cs new file mode 100644 index 00000000..f28bee5e --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanCacheItem.cs @@ -0,0 +1,9 @@ +using System; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +[Serializable] +public class FlashSalesPlanCacheItem : FlashSalesPlanDto +{ +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultAppService.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultAppService.cs new file mode 100644 index 00000000..854ca5e2 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultAppService.cs @@ -0,0 +1,51 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults.Dtos; +using EasyAbp.EShop.Plugins.FlashSales.Permissions; +using Volo.Abp.Application.Services; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +public class FlashSalesResultAppService : + ReadOnlyAppService, + IFlashSalesResultAppService +{ + protected override string GetPolicyName { get; set; } + protected override string GetListPolicyName { get; set; } + + protected IFlashSalesResultRepository FlashSalesResultRepository { get; } + + public FlashSalesResultAppService(IFlashSalesResultRepository flashSalesResultRepository) : base(flashSalesResultRepository) + { + } + + public override async Task GetAsync(Guid id) + { + await CheckGetPolicyAsync(); + + var flashSalesPlan = await GetEntityByIdAsync(id); + + if (flashSalesPlan.UserId != CurrentUser.Id) + { + await CheckPolicyAsync(FlashSalesPermissions.FlashSalesResult.Manage); + } + + return await MapToGetOutputDtoAsync(flashSalesPlan); + } + + protected override async Task> CreateFilteredQueryAsync(FlashSalesResultGetListInput input) + { + if (input.UserId != CurrentUser.Id) + { + await CheckPolicyAsync(FlashSalesPermissions.FlashSalesResult.Manage); + } + + return (await base.CreateFilteredQueryAsync(input)) + .WhereIf(input.StoreId.HasValue, x => x.StoreId == input.StoreId.Value) + .WhereIf(input.PlanId.HasValue, x => x.PlanId == input.PlanId.Value) + .WhereIf(input.Status.HasValue, x => x.Status == input.Status.Value) + .WhereIf(input.UserId.HasValue, x => x.UserId == input.UserId.Value) + .WhereIf(input.OrderId.HasValue, x => x.OrderId == input.OrderId.Value); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared.csproj b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared.csproj index e5e0cdcf..95717151 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared.csproj +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared.csproj @@ -21,4 +21,8 @@ + + + + diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesErrorCodes.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesErrorCodes.cs index b02a0801..033cd4a7 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesErrorCodes.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesErrorCodes.cs @@ -6,4 +6,17 @@ public static class FlashSalesErrorCodes public const string EndTimeMustBeLaterThanBeginTime = $"{Namespace}:{nameof(EndTimeMustBeLaterThanBeginTime)}"; + public const string ProductIsNotPublished = $"{Namespace}:{nameof(ProductIsNotPublished)}"; + + public const string IsNotFlashSalesProduct = $"{Namespace}:{nameof(IsNotFlashSalesProduct)}"; + + public const string PreOrderExipred = $"{Namespace}:{nameof(PreOrderExipred)}"; + + public const string FlashSalesPlanIsNotStart = $"{Namespace}:{nameof(FlashSalesPlanIsNotStart)}"; + + public const string FlashSalesPlanIsExpired = $"{Namespace}:{nameof(FlashSalesPlanIsExpired)}"; + + public const string CreateFlashSalesOrderBusy = $"{Namespace}:{nameof(CreateFlashSalesOrderBusy)}"; + + public const string AlreadySubmitCreateFlashSalesOrder = $"{Namespace}:{nameof(AlreadySubmitCreateFlashSalesOrder)}"; } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/CreateFlashSalesOrderCompleteEto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/CreateFlashSalesOrderCompleteEto.cs new file mode 100644 index 00000000..5c6942b5 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/CreateFlashSalesOrderCompleteEto.cs @@ -0,0 +1,25 @@ +using System; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using Volo.Abp.MultiTenancy; +using Volo.Abp.ObjectExtending; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class CreateFlashSalesOrderCompleteEto : ExtensibleObject, IMultiTenant +{ + public Guid? TenantId { get; set; } + + public Guid PendingResultId { get; set; } + + public bool Success { get; set; } + + public Guid StoreId { get; set; } + + public Guid PlanId { get; set; } + + public string Reason { get; set; } + + public Guid UserId { get; set; } + + public Guid? OrderId { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/CreateFlashSalesOrderEto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/CreateFlashSalesOrderEto.cs new file mode 100644 index 00000000..27a45274 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/CreateFlashSalesOrderEto.cs @@ -0,0 +1,32 @@ +using System; +using EasyAbp.EShop.Products.Products; +using Volo.Abp.MultiTenancy; +using Volo.Abp.ObjectExtending; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +[Serializable] +public class CreateFlashSalesOrderEto : ExtensibleObject, IMultiTenant +{ + public Guid? TenantId { get; set; } + + public Guid StoreId { get; set; } + + public Guid PlanId { get; set; } + + public Guid UserId { get; set; } + + public Guid PendingResultId { get; set; } + + public DateTime CreateTime { get; set; } + + public string CustomerRemark { get; set; } + + public int Quantity { get; set; } + + public FlashSalesProductEto Product { get; set; } + + public FlashSalesProductDetailEto ProductDetail { get; set; } + + public FlashSalesPlanEto Plan { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanEto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanEto.cs new file mode 100644 index 00000000..23450eca --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanEto.cs @@ -0,0 +1,22 @@ +using System; +using Volo.Abp.MultiTenancy; +using Volo.Abp.ObjectExtending; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class FlashSalesPlanEto : FullAuditedEntityEto, IMultiTenant +{ + public Guid? TenantId { get; set; } + + public Guid StoreId { get; set; } + + public DateTime BeginTime { get; set; } + + public DateTime EndTime { get; set; } + + public Guid ProductId { get; set; } + + public Guid ProductSkuId { get; set; } + + public bool IsPublished { get; set; } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductAttributeEto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductAttributeEto.cs new file mode 100644 index 00000000..c26be79e --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductAttributeEto.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using EasyAbp.EShop.Products.Products; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class FlashSalesProductAttributeEto : FullAuditedEntityEto, IProductAttribute +{ + public string DisplayName { get; set; } + + public string Description { get; set; } + + public int DisplayOrder { get; set; } + + public List ProductAttributeOptions { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductAttributeOptionEto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductAttributeOptionEto.cs new file mode 100644 index 00000000..3e613049 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductAttributeOptionEto.cs @@ -0,0 +1,13 @@ +using System; +using EasyAbp.EShop.Products.Products; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class FlashSalesProductAttributeOptionEto : FullAuditedEntityEto, IProductAttributeOption +{ + public string DisplayName { get; set; } + + public string Description { get; set; } + + public int DisplayOrder { get; set; } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductEto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductEto.cs new file mode 100644 index 00000000..7a0a4a99 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductEto.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using EasyAbp.EShop.Products.Products; +using Volo.Abp.MultiTenancy; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class FlashSalesProductEto : FullAuditedEntityEto, IProduct, IMultiTenant +{ + public Guid? TenantId { get; set; } + + public Guid StoreId { get; set; } + + public string ProductGroupName { get; set; } + + public Guid? ProductDetailId { get; set; } + + public string UniqueName { get; set; } + + public string DisplayName { get; set; } + + public InventoryStrategy InventoryStrategy { get; set; } + + public string InventoryProviderName { get; set; } + + public string MediaResources { get; set; } + + public int DisplayOrder { get; set; } + + public bool IsPublished { get; set; } + + public bool IsStatic { get; set; } + + public bool IsHidden { get; set; } + + public List ProductAttributes { get; set; } + + public List ProductSkus { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductSkuEto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductSkuEto.cs new file mode 100644 index 00000000..09abe06c --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesProductSkuEto.cs @@ -0,0 +1,25 @@ +using System; +using EasyAbp.EShop.Products.Products; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class FlashSalesProductSkuEto : FullAuditedEntityEto, IProductSku +{ + public string SerializedAttributeOptionIds { get; set; } + + public string Name { get; set; } + + public string Currency { get; set; } + + public decimal? OriginalPrice { get; set; } + + public decimal Price { get; set; } + + public int OrderMinQuantity { get; set; } + + public int OrderMaxQuantity { get; set; } + + public string MediaResources { get; set; } + + public Guid? ProductDetailId { get; set; } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/ProductDetailEto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/ProductDetailEto.cs new file mode 100644 index 00000000..d9ebef4d --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/ProductDetailEto.cs @@ -0,0 +1,10 @@ +using System; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class FlashSalesProductDetailEto : FullAuditedEntityEto +{ + public Guid? StoreId { get; set; } + + public string Description { get; set; } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultStatus.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultStatus.cs new file mode 100644 index 00000000..3d88d0cc --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultStatus.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +public enum FlashSalesResultStatus +{ + Pending, + Successful, + Failed +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FullAuditedEntityEto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FullAuditedEntityEto.cs new file mode 100644 index 00000000..7961d1f6 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FullAuditedEntityEto.cs @@ -0,0 +1,23 @@ +using System; +using Volo.Abp.ObjectExtending; + +namespace EasyAbp.EShop.Plugins.FlashSales; + +public class FullAuditedEntityEto : ExtensibleObject +{ + public TPrimaryKey Id { get; set; } + + public DateTime CreationTime { get; set; } + + public Guid? CreatorId { get; set; } + + public DateTime? LastModificationTime { get; set; } + + public Guid? LastModifierId { get; set; } + + public bool IsDeleted { get; set; } + + public Guid? DeleterId { get; set; } + + public DateTime? DeletionTime { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/FlashSalesResource.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/FlashSalesResource.cs index a6e9fa61..b2519b45 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/FlashSalesResource.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/FlashSalesResource.cs @@ -2,7 +2,7 @@ namespace EasyAbp.EShop.Plugins.FlashSales.Localization; -[LocalizationResourceName("FlashSales")] +[LocalizationResourceName("EasyAbpEShopPluginsFlashSales")] public class FlashSalesResource { diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/en.json b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/en.json index 189662ee..f92545a9 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/en.json +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/en.json @@ -1,5 +1,34 @@ { "culture": "en", "texts": { + "EasyAbp.EShop.Plugins.FlashSales:EndTimeMustBeLaterThanBeginTime": "End time must be later than start time", + "Menu:FlashSalesManagement": "FlashSalesManagement", + "Permission:FlashSalesPlan": "FlashSalesPlan", + "Permission:Manage": "Manage", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Menu:FlashSalesPlan": "FlashSalesPlan", + "FlashSalesPlan": "FlashSalesPlan", + "FlashSalesPlanStoreId": "Store ID", + "FlashSalesPlanBeginTime": "Begin Time", + "FlashSalesPlanEndTime": "End Time", + "FlashSalesPlanProductId": "Product ID", + "FlashSalesPlanProductSkuId": "Product SKU ID", + "FlashSalesPlanIsPublished": "Is Published", + "CreateFlashSalesPlan": "Create", + "EditFlashSalesPlan": "Edit", + "FlashSalesPlanDeletionConfirmationMessage": "Are you sure to delete the flashSalesPlan {0}?", + "SuccessfullyDeleted": "Successfully deleted", + "Permission:FlashSalesResult": "FlashSalesResult", + "Menu:FlashSalesResult": "FlashSalesResult", + "FlashSalesResult": "FlashSalesResult", + "FlashSalesResultStoreId": "Store ID", + "FlashSalesResultPlanId": "Plan ID", + "FlashSalesResultStatus": "Status", + "FlashSalesResultUserId": "User ID", + "FlashSalesResultOrderId": "Order ID", + "FlashSalesResultCreationTime": "Creation Time", + "ViewFlashSalesPlan": "View" } -} \ No newline at end of file +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hans.json b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hans.json index df772fa6..5061f16b 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hans.json +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hans.json @@ -1,5 +1,34 @@ { "culture": "zh-Hans", "texts": { + "EasyAbp.EShop.Plugins.FlashSales:EndTimeMustBeLaterThanBeginTime": "结束时间必须晚于开始时间", + "Menu:FlashSalesManagement": "闪购", + "Permission:FlashSalesPlan": "闪购计划", + "Permission:Manage": "管理", + "Permission:Create": "新建", + "Permission:Update": "更新", + "Permission:Delete": "删除", + "Menu:FlashSalesPlan": "闪购计划", + "FlashSalesPlan": "闪购计划", + "FlashSalesPlanStoreId": "店铺 ID", + "FlashSalesPlanBeginTime": "开始时间", + "FlashSalesPlanEndTime": "结束时间", + "FlashSalesPlanProductId": "产品 ID", + "FlashSalesPlanProductSkuId": "产品SKU ID", + "FlashSalesPlanIsPublished": "发布", + "CreateFlashSalesPlan": "新建", + "EditFlashSalesPlan": "编辑", + "FlashSalesPlanDeletionConfirmationMessage": "确认删除闪购计划 {0}?", + "SuccessfullyDeleted": "删除成功", + "Permission:FlashSalesResult": "闪购结果", + "Menu:FlashSalesResult": "闪购结果", + "FlashSalesResult": "闪购结果", + "FlashSalesResultStoreId": "店铺 ID", + "FlashSalesResultPlanId": "计划 ID", + "FlashSalesResultStatus": "状态", + "FlashSalesResultUserId": "用户 ID", + "FlashSalesResultOrderId": "订单 ID", + "FlashSalesResultCreationTime": "创建时间", + "ViewFlashSalesPlan": "查看" } -} \ No newline at end of file +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hant.json b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hant.json index 7de37982..24fd0adc 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hant.json +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hant.json @@ -1,5 +1,34 @@ { "culture": "zh-Hant", "texts": { + "EasyAbp.EShop.Plugins.FlashSales:EndTimeMustBeLaterThanBeginTime": "結束時間必須晚於開始時間", + "Menu:FlashSalesManagement": "FlashSalesManagement", + "Permission:FlashSalesPlan": "FlashSalesPlan", + "Permission:Manage": "Manage", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Menu:FlashSalesPlan": "FlashSalesPlan", + "FlashSalesPlan": "FlashSalesPlan", + "FlashSalesPlanStoreId": "FlashSalesPlanStoreId", + "FlashSalesPlanBeginTime": "FlashSalesPlanBeginTime", + "FlashSalesPlanEndTime": "FlashSalesPlanEndTime", + "FlashSalesPlanProductId": "FlashSalesPlanProductId", + "FlashSalesPlanProductSkuId": "FlashSalesPlanProductSkuId", + "FlashSalesPlanIsPublished": "FlashSalesPlanIsActive", + "CreateFlashSalesPlan": "CreateFlashSalesPlan", + "EditFlashSalesPlan": "EditFlashSalesPlan", + "FlashSalesPlanDeletionConfirmationMessage": "Are you sure to delete the flashSalesPlan {0}?", + "SuccessfullyDeleted": "Successfully deleted", + "Permission:FlashSalesResult": "闪购结果", + "Menu:FlashSalesResult": "闪购计划", + "FlashSalesResult": "闪购结果", + "FlashSalesResultStoreId": "店铺 ID", + "FlashSalesResultPlanId": "计划 ID", + "FlashSalesResultStatus": "状态", + "FlashSalesResultUserId": "用户 ID", + "FlashSalesResultOrderId": "订单 ID", + "FlashSalesResultCreationTime": "创建时间", + "ViewFlashSalesPlan": "查看" } -} \ No newline at end of file +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp.EShop.Plugins.FlashSales.Domain.csproj b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp.EShop.Plugins.FlashSales.Domain.csproj index 87ad5a39..b8f4224b 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp.EShop.Plugins.FlashSales.Domain.csproj +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp.EShop.Plugins.FlashSales.Domain.csproj @@ -8,6 +8,7 @@ + diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesDomainAutoMapperProfile.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesDomainAutoMapperProfile.cs new file mode 100644 index 00000000..df4eb669 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesDomainAutoMapperProfile.cs @@ -0,0 +1,16 @@ +using AutoMapper; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +namespace EasyAbp.EShop.Plugins.FlashSales; + +public class EShopPluginsFlashSalesDomainAutoMapperProfile : Profile +{ + public EShopPluginsFlashSalesDomainAutoMapperProfile() + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + CreateMap() + .MapExtraProperties(); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesDomainModule.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesDomainModule.cs index f3b45e32..0ce9dd05 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesDomainModule.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/EShopPluginsFlashSalesDomainModule.cs @@ -1,13 +1,33 @@ -using Volo.Abp.Domain; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AutoMapper; +using Volo.Abp.Domain; +using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Modularity; namespace EasyAbp.EShop.Plugins.FlashSales; [DependsOn( typeof(AbpDddDomainModule), + typeof(AbpAutoMapperModule), typeof(EShopPluginsFlashSalesDomainSharedModule) )] public class EShopPluginsFlashSalesDomainModule : AbpModule { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + Configure(options => + { + options.AddProfile(validate: true); + }); + + Configure(options => + { + options.EtoMappings.Add(typeof(EShopPluginsFlashSalesDomainModule)); + + options.AutoEventSelectors.Add(); + }); + } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesDbProperties.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesDbProperties.cs index e94eef4d..909df743 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesDbProperties.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesDbProperties.cs @@ -2,9 +2,9 @@ public static class FlashSalesDbProperties { - public static string DbTablePrefix { get; set; } = "FlashSales"; + public static string DbTablePrefix { get; set; } = "EasyAbpEShopPluginsFlashSales"; public static string DbSchema { get; set; } = null; - public const string ConnectionStringName = "FlashSales"; + public const string ConnectionStringName = "EasyAbpEShopPluginsFlashSales"; } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/EndTimeMustBeLaterThanBeginTimeException.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/EndTimeMustBeLaterThanBeginTimeException.cs new file mode 100644 index 00000000..4b9fdad2 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/EndTimeMustBeLaterThanBeginTimeException.cs @@ -0,0 +1,12 @@ +using Volo.Abp; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +internal class EndTimeMustBeLaterThanBeginTimeException : BusinessException +{ + public EndTimeMustBeLaterThanBeginTimeException() + : base(FlashSalesErrorCodes.EndTimeMustBeLaterThanBeginTime) + { + + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan.cs new file mode 100644 index 00000000..0de27f9a --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan.cs @@ -0,0 +1,58 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class FlashSalesPlan : FullAuditedAggregateRoot, IMultiTenant +{ + public virtual Guid? TenantId { get; protected set; } + + public virtual Guid StoreId { get; protected set; } + + public virtual DateTime BeginTime { get; set; } + + public virtual DateTime EndTime { get; set; } + + public virtual Guid ProductId { get; protected set; } + + public virtual Guid ProductSkuId { get; protected set; } + + public virtual bool IsPublished { get; protected set; } + + protected FlashSalesPlan() + { + } + + public FlashSalesPlan(Guid id, Guid? tenantId, Guid storeId, DateTime beginTime, DateTime endTime, Guid productId, Guid productSkuId, bool isPublished) + : base(id) + { + TenantId = tenantId; + StoreId = storeId; + SetTimeRange(beginTime, endTime); + SetProduct(productId, productSkuId); + SetPublished(isPublished); + } + + public void SetTimeRange(DateTime beginTime, DateTime endTime) + { + if (beginTime > endTime) + { + throw new EndTimeMustBeLaterThanBeginTimeException(); + } + + BeginTime = beginTime; + EndTime = endTime; + } + + public void SetProduct(Guid productId, Guid productSkuId) + { + ProductId = productId; + ProductSkuId = productSkuId; + } + + public void SetPublished(bool isPublished) + { + IsPublished = isPublished; + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanManager.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanManager.cs new file mode 100644 index 00000000..d8654316 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanManager.cs @@ -0,0 +1,44 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Domain.Services; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class FlashSalesPlanManager : DomainService +{ + public virtual Task CreateAsync( + Guid storeId, + DateTime beginTime, + DateTime endTime, + Guid productId, + Guid productSkuId, + bool isActive) + { + var flashSalesPlan = new FlashSalesPlan( + GuidGenerator.Create(), + CurrentTenant.Id, + storeId, + beginTime, + endTime, + productId, + productSkuId, + isActive + ); + return Task.FromResult(flashSalesPlan); + } + + public virtual Task UpdateAsync( + FlashSalesPlan flashSalesPlan, + DateTime beginTime, + DateTime endTime, + Guid productId, + Guid productSkuId, + bool isPublished) + { + flashSalesPlan.SetTimeRange(beginTime, endTime); + flashSalesPlan.SetProduct(productId, productSkuId); + flashSalesPlan.SetPublished(isPublished); + + return Task.FromResult(flashSalesPlan); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/IFlashSalesPlanRepository.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/IFlashSalesPlanRepository.cs new file mode 100644 index 00000000..41f32db0 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/IFlashSalesPlanRepository.cs @@ -0,0 +1,8 @@ +using System; +using Volo.Abp.Domain.Repositories; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public interface IFlashSalesPlanRepository : IRepository +{ +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/CreateFlashSalesOrderCompleteEventHandler.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/CreateFlashSalesOrderCompleteEventHandler.cs new file mode 100644 index 00000000..b7dc305a --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/CreateFlashSalesOrderCompleteEventHandler.cs @@ -0,0 +1,37 @@ +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Guids; +using Volo.Abp.Uow; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +public class CreateFlashSalesOrderCompleteEventHandler : IDistributedEventHandler, ITransientDependency +{ + protected IFlashSalesResultRepository FlashSalesResultRepository { get; } + protected IGuidGenerator GuidGenerator { get; } + + public CreateFlashSalesOrderCompleteEventHandler(IFlashSalesResultRepository flashSalesResultRepository, IGuidGenerator guidGenerator) + { + FlashSalesResultRepository = flashSalesResultRepository; + GuidGenerator = guidGenerator; + } + + [UnitOfWork] + public virtual async Task HandleEventAsync(CreateFlashSalesOrderCompleteEto eventData) + { + var flashSalesResult = await FlashSalesResultRepository.GetAsync(eventData.PendingResultId); + + if (eventData.Success) + { + flashSalesResult.MarkAsSuccessful(eventData.OrderId.Value); + } + else + { + flashSalesResult.MarkAsFailed(eventData.Reason); + } + + await FlashSalesResultRepository.UpdateAsync(flashSalesResult, autoSave: true); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult.cs new file mode 100644 index 00000000..de3a83df --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult.cs @@ -0,0 +1,49 @@ +using System; +using Volo.Abp; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +public class FlashSalesResult : FullAuditedAggregateRoot, IMultiTenant +{ + public virtual Guid? TenantId { get; protected set; } + + public virtual Guid StoreId { get; protected set; } + + public virtual Guid PlanId { get; protected set; } + + public virtual FlashSalesResultStatus Status { get; protected set; } + + public virtual string Reason { get; protected set; } + + public virtual Guid UserId { get; protected set; } + + public virtual Guid? OrderId { get; protected set; } + + protected FlashSalesResult() { } + + public FlashSalesResult(Guid id, Guid? tenantId, Guid storeId, Guid planId, FlashSalesResultStatus status, string reason, Guid userId, Guid? orderId) + : base(id) + { + TenantId = tenantId; + StoreId = storeId; + PlanId = planId; + Status = status; + Reason = reason; + UserId = userId; + OrderId = orderId; + } + + public void MarkAsSuccessful(Guid orderId) + { + Status = FlashSalesResultStatus.Successful; + OrderId = orderId; + } + + public void MarkAsFailed(string reason) + { + Status = FlashSalesResultStatus.Failed; + Reason = Check.NotNullOrEmpty(reason, nameof(reason)); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/IFlashSalesResultRepository.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/IFlashSalesResultRepository.cs new file mode 100644 index 00000000..d09be083 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/IFlashSalesResultRepository.cs @@ -0,0 +1,9 @@ +using System; +using Volo.Abp.Domain.Repositories; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +public interface IFlashSalesResultRepository : IRepository +{ + +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/EShopPluginsFlashSalesEntityFrameworkCoreModule.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/EShopPluginsFlashSalesEntityFrameworkCoreModule.cs index 07383dc2..a573c7e9 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/EShopPluginsFlashSalesEntityFrameworkCoreModule.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/EShopPluginsFlashSalesEntityFrameworkCoreModule.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.DependencyInjection; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.Modularity; @@ -14,9 +16,8 @@ public class EShopPluginsFlashSalesEntityFrameworkCoreModule : AbpModule { context.Services.AddAbpDbContext(options => { - /* Add custom repositories here. Example: - * options.AddRepository(); - */ + options.AddRepository(); + options.AddRepository(); }); } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/FlashSalesDbContext.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/FlashSalesDbContext.cs index 3d3df1b4..41d0d253 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/FlashSalesDbContext.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/FlashSalesDbContext.cs @@ -1,4 +1,6 @@ -using Microsoft.EntityFrameworkCore; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using Microsoft.EntityFrameworkCore; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; @@ -7,9 +9,9 @@ namespace EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore; [ConnectionStringName(FlashSalesDbProperties.ConnectionStringName)] public class FlashSalesDbContext : AbpDbContext, IFlashSalesDbContext { - /* Add DbSet for each Aggregate Root here. Example: - * public DbSet Questions { get; set; } - */ + public DbSet Plans { get; set; } + + public DbSet Results { get; set; } public FlashSalesDbContext(DbContextOptions options) : base(options) @@ -21,6 +23,6 @@ public class FlashSalesDbContext : AbpDbContext, IFlashSale { base.OnModelCreating(builder); - builder.ConfigureFlashSales(); + builder.ConfigureEShopPluginsFlashSales(); } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/FlashSalesDbContextModelCreatingExtensions.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/FlashSalesDbContextModelCreatingExtensions.cs index 209d4ba8..284a5122 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/FlashSalesDbContextModelCreatingExtensions.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/FlashSalesDbContextModelCreatingExtensions.cs @@ -1,33 +1,32 @@ -using Microsoft.EntityFrameworkCore; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using Microsoft.EntityFrameworkCore; using Volo.Abp; +using Volo.Abp.EntityFrameworkCore.Modeling; namespace EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore; public static class FlashSalesDbContextModelCreatingExtensions { - public static void ConfigureFlashSales( + public static void ConfigureEShopPluginsFlashSales( this ModelBuilder builder) { Check.NotNull(builder, nameof(builder)); - /* Configure all entities here. Example: - - builder.Entity(b => + builder.Entity(b => { - //Configure table & schema name - b.ToTable(FlashSalesDbProperties.DbTablePrefix + "Questions", FlashSalesDbProperties.DbSchema); - + b.ToTable(FlashSalesDbProperties.DbTablePrefix + "Plans", FlashSalesDbProperties.DbSchema); b.ConfigureByConvention(); - //Properties - b.Property(q => q.Title).IsRequired().HasMaxLength(QuestionConsts.MaxTitleLength); + /* Configure more properties here */ + }); - //Relations - b.HasMany(question => question.Tags).WithOne().HasForeignKey(qt => qt.QuestionId); + builder.Entity(b => + { + b.ToTable(FlashSalesDbProperties.DbTablePrefix + "Results", FlashSalesDbProperties.DbSchema); + b.ConfigureByConvention(); - //Indexes - b.HasIndex(q => q.CreationTime); + /* Configure more properties here */ }); - */ } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/IFlashSalesDbContext.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/IFlashSalesDbContext.cs index 5804039f..46a6766b 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/IFlashSalesDbContext.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/EntityFrameworkCore/IFlashSalesDbContext.cs @@ -1,4 +1,7 @@ -using Volo.Abp.Data; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; namespace EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore; @@ -6,7 +9,7 @@ namespace EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore; [ConnectionStringName(FlashSalesDbProperties.ConnectionStringName)] public interface IFlashSalesDbContext : IEfCoreDbContext { - /* Add DbSet for each Aggregate Root here. Example: - * DbSet Questions { get; } - */ + DbSet Plans { get; set; } + + DbSet Results { get; set; } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/EfCoreFlashSalesPlanRepository.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/EfCoreFlashSalesPlanRepository.cs new file mode 100644 index 00000000..7926de36 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/EfCoreFlashSalesPlanRepository.cs @@ -0,0 +1,21 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans +{ + public class EfCoreFlashSalesPlanRepository : EfCoreRepository, IFlashSalesPlanRepository + { + public EfCoreFlashSalesPlanRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanEfCoreQuerableExtensions.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanEfCoreQuerableExtensions.cs new file mode 100644 index 00000000..5bccbeee --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanEfCoreQuerableExtensions.cs @@ -0,0 +1,18 @@ +using System.Linq; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public static class FlashSalesPlanEfCoreQueryableExtensions +{ + public static IQueryable IncludeDetails(this IQueryable queryable, bool include = true) + { + if (!include) + { + return queryable; + } + + return queryable + // .Include(x => x.xxx) // TODO: AbpHelper generated + ; + } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/EfCoreFlashSalesResultRepository.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/EfCoreFlashSalesResultRepository.cs new file mode 100644 index 00000000..e4fc4185 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/EfCoreFlashSalesResultRepository.cs @@ -0,0 +1,20 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +public class EfCoreFlashSalesResultRepository : EfCoreRepository, IFlashSalesResultRepository +{ + public EfCoreFlashSalesResultRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultEfCoreQuerableExtensions.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultEfCoreQuerableExtensions.cs new file mode 100644 index 00000000..141898bd --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.EntityFrameworkCore/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultEfCoreQuerableExtensions.cs @@ -0,0 +1,16 @@ +using System.Linq; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +public static class FlashSalesResultEfCoreQuerableExtensions +{ + public static IQueryable IncludeDetails(this IQueryable queryable, bool include = true) + { + if (!include) + { + return queryable; + } + + return queryable; + } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.HttpApi/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanController.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.HttpApi/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanController.cs new file mode 100644 index 00000000..1bd611d8 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.HttpApi/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanController.cs @@ -0,0 +1,71 @@ +using System; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +[Area(EShopPluginsFlashSalesRemoteServiceConsts.ModuleName)] +[RemoteService(Name = EShopPluginsFlashSalesRemoteServiceConsts.RemoteServiceName)] +[Route("/api/e-shop/plugins/flash-sales/flash-sales-plan")] +public class FlashSalesPlanController : + FlashSalesController, + IFlashSalesPlanAppService +{ + protected IFlashSalesPlanAppService Service { get; } + + public FlashSalesPlanController(IFlashSalesPlanAppService flashSalesPlanAppService) + { + Service = flashSalesPlanAppService; + } + + [HttpGet("{id}")] + public virtual Task GetAsync(Guid id) + { + return Service.GetAsync(id); + } + + [HttpGet] + public virtual Task> GetListAsync(FlashSalesPlanGetListInput input) + { + return Service.GetListAsync(input); + } + + [HttpPost("{id}")] + public virtual Task CreateAsync(FlashSalesPlanCreateDto input) + { + return Service.CreateAsync(input); + } + + [HttpPut("{id}")] + public virtual Task UpdateAsync(Guid id, FlashSalesPlanUpdateDto input) + { + return Service.UpdateAsync(id, input); + } + + [HttpDelete("{id}")] + public virtual Task DeleteAsync(Guid id) + { + return Service.DeleteAsync(id); + } + + [HttpPost("{id}/pre-order")] + public virtual Task PreOrderAsync(Guid id) + { + return Service.PreOrderAsync(id); + } + + [HttpGet("{id}/check-pre-order")] + public virtual Task CheckPreOrderAsync(Guid id) + { + return Service.CheckPreOrderAsync(id); + } + + [HttpPost("{id}/order")] + public virtual Task CreateOrderAsync(Guid id, CreateOrderInput input) + { + return Service.CreateOrderAsync(id, input); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.HttpApi/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultController.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.HttpApi/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultController.cs new file mode 100644 index 00000000..f74846e3 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.HttpApi/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResultController.cs @@ -0,0 +1,33 @@ +using System; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults.Dtos; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +[Area(EShopPluginsFlashSalesRemoteServiceConsts.ModuleName)] +[RemoteService(Name = EShopPluginsFlashSalesRemoteServiceConsts.RemoteServiceName)] +[Route("/api/e-shop/plugins/flash-sales/flash-sales-result")] +public class FlashSalesResultController : FlashSalesController, IFlashSalesResultAppService +{ + protected IFlashSalesResultAppService Service { get; } + + public FlashSalesResultController(IFlashSalesResultAppService service) + { + Service = service; + } + + [HttpGet("{id}")] + public virtual Task GetAsync(Guid id) + { + return Service.GetAsync(id); + } + + [HttpGet] + public virtual Task> GetListAsync(FlashSalesResultGetListInput input) + { + return Service.GetListAsync(input); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/MongoFlashSalesPlanRepository.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/MongoFlashSalesPlanRepository.cs new file mode 100644 index 00000000..e573f156 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/MongoFlashSalesPlanRepository.cs @@ -0,0 +1,13 @@ +using System; +using EasyAbp.EShop.Plugins.FlashSales.MongoDB; +using Volo.Abp.Domain.Repositories.MongoDB; +using Volo.Abp.MongoDB; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +public class MongoFlashSalesPlanRepository : MongoDbRepository, IFlashSalesPlanRepository +{ + public MongoFlashSalesPlanRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/MongoFlashSalesResultRepository.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/MongoFlashSalesResultRepository.cs new file mode 100644 index 00000000..8621e83e --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/FlashSalesResults/MongoFlashSalesResultRepository.cs @@ -0,0 +1,13 @@ +using System; +using EasyAbp.EShop.Plugins.FlashSales.MongoDB; +using Volo.Abp.Domain.Repositories.MongoDB; +using Volo.Abp.MongoDB; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +public class MongoFlashSalesResultRepository : MongoDbRepository, IFlashSalesResultRepository +{ + public MongoFlashSalesResultRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/EShopPluginsFlashSalesMongoDbModule.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/EShopPluginsFlashSalesMongoDbModule.cs index 9e39be35..728dbbde 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/EShopPluginsFlashSalesMongoDbModule.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/EShopPluginsFlashSalesMongoDbModule.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.DependencyInjection; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; using Volo.Abp.MongoDB; @@ -14,9 +16,8 @@ public class EShopPluginsFlashSalesMongoDbModule : AbpModule { context.Services.AddMongoDbContext(options => { - /* Add custom repositories here. Example: - * options.AddRepository(); - */ + options.AddRepository(); + options.AddRepository(); }); } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/FlashSalesMongoDbContext.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/FlashSalesMongoDbContext.cs index 537a2714..3e2028e8 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/FlashSalesMongoDbContext.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/FlashSalesMongoDbContext.cs @@ -1,4 +1,7 @@ -using Volo.Abp.Data; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using MongoDB.Driver; +using Volo.Abp.Data; using Volo.Abp.MongoDB; namespace EasyAbp.EShop.Plugins.FlashSales.MongoDB; @@ -6,9 +9,9 @@ namespace EasyAbp.EShop.Plugins.FlashSales.MongoDB; [ConnectionStringName(FlashSalesDbProperties.ConnectionStringName)] public class FlashSalesMongoDbContext : AbpMongoDbContext, IFlashSalesMongoDbContext { - /* Add mongo collections here. Example: - * public IMongoCollection Questions => Collection(); - */ + public IMongoCollection Plans => Collection(); + + public IMongoCollection Results => Collection(); protected override void CreateModel(IMongoModelBuilder modelBuilder) { diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/FlashSalesMongoDbContextExtensions.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/FlashSalesMongoDbContextExtensions.cs index 91b45a39..5bdad8d4 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/FlashSalesMongoDbContextExtensions.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/FlashSalesMongoDbContextExtensions.cs @@ -1,4 +1,6 @@ -using Volo.Abp; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using Volo.Abp; using Volo.Abp.MongoDB; namespace EasyAbp.EShop.Plugins.FlashSales.MongoDB; @@ -9,5 +11,9 @@ public static class FlashSalesMongoDbContextExtensions this IMongoModelBuilder builder) { Check.NotNull(builder, nameof(builder)); + + builder.Entity(b => b.CollectionName = FlashSalesDbProperties.DbTablePrefix + "Plans"); + + builder.Entity(b => b.CollectionName = FlashSalesDbProperties.DbTablePrefix + "Results"); } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/IFlashSalesMongoDbContext.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/IFlashSalesMongoDbContext.cs index d0501265..5cc3f8e8 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/IFlashSalesMongoDbContext.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.MongoDB/EasyAbp/EShop/Plugins/FlashSales/MongoDB/IFlashSalesMongoDbContext.cs @@ -1,4 +1,7 @@ -using Volo.Abp.Data; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using MongoDB.Driver; +using Volo.Abp.Data; using Volo.Abp.MongoDB; namespace EasyAbp.EShop.Plugins.FlashSales.MongoDB; @@ -6,7 +9,7 @@ namespace EasyAbp.EShop.Plugins.FlashSales.MongoDB; [ConnectionStringName(FlashSalesDbProperties.ConnectionStringName)] public interface IFlashSalesMongoDbContext : IAbpMongoDbContext { - /* Define mongo collections here. Example: - * IMongoCollection Questions { get; } - */ + IMongoCollection Plans { get; } + + IMongoCollection Results { get; } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EShopPluginsFlashSalesWebAutoMapperProfile.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EShopPluginsFlashSalesWebAutoMapperProfile.cs index a6afd47a..4eb9cde3 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EShopPluginsFlashSalesWebAutoMapperProfile.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EShopPluginsFlashSalesWebAutoMapperProfile.cs @@ -1,4 +1,8 @@ using AutoMapper; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults.Dtos; +using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan.ViewModels; +using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesResults.FlashSalesResult.ViewModels; namespace EasyAbp.EShop.Plugins.FlashSales.Web; @@ -9,5 +13,13 @@ public class EShopPluginsFlashSalesWebAutoMapperProfile : Profile /* You can configure your AutoMapper mapping configuration here. * Alternatively, you can split your mapping configurations * into multiple profile classes for a better organization. */ + CreateMap() + .ForMember(dest => dest.ExtraProperties, opt => opt.Ignore()); + CreateMap() + .ForMember(dest => dest.ExtraProperties, opt => opt.Ignore()); + CreateMap() + .ForSourceMember(dest => dest.ExtraProperties, opt => opt.DoNotValidate()); + CreateMap() + .ForSourceMember(dest => dest.ExtraProperties, opt => opt.DoNotValidate()); } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EShopPluginsFlashSalesWebModule.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EShopPluginsFlashSalesWebModule.cs index 41e96f9d..443dc336 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EShopPluginsFlashSalesWebModule.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EShopPluginsFlashSalesWebModule.cs @@ -53,6 +53,6 @@ public class EShopPluginsFlashSalesWebModule : AbpModule Configure(options => { //Configure authorization. - }); + }); } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EasyAbp.EShop.Plugins.FlashSales.Web.csproj b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EasyAbp.EShop.Plugins.FlashSales.Web.csproj index cedf9892..94d9b52e 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EasyAbp.EShop.Plugins.FlashSales.Web.csproj +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/EasyAbp.EShop.Plugins.FlashSales.Web.csproj @@ -37,4 +37,9 @@ + + + + + diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Menus/FlashSalesMenuContributor.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Menus/FlashSalesMenuContributor.cs index e5f8ec0f..6ab46dea 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Menus/FlashSalesMenuContributor.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Menus/FlashSalesMenuContributor.cs @@ -1,4 +1,7 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.Localization; +using EasyAbp.EShop.Plugins.FlashSales.Permissions; using Volo.Abp.UI.Navigation; namespace EasyAbp.EShop.Plugins.FlashSales.Web.Menus; @@ -13,11 +16,40 @@ public class FlashSalesMenuContributor : IMenuContributor } } - private Task ConfigureMainMenuAsync(MenuConfigurationContext context) + private async Task ConfigureMainMenuAsync(MenuConfigurationContext context) { + var l = context.GetLocalizer(); //Add main menu items. - context.Menu.AddItem(new ApplicationMenuItem(FlashSalesMenus.Prefix, displayName: "FlashSales", "~/FlashSales", icon: "fa fa-globe")); + var flashSalesManagementMenuItem = new ApplicationMenuItem(FlashSalesMenus.Prefix, l["Menu:FlashSalesManagement"]); - return Task.CompletedTask; + if (await context.IsGrantedAsync(FlashSalesPermissions.FlashSalesPlan.Default)) + { + flashSalesManagementMenuItem.AddItem( + new ApplicationMenuItem( + FlashSalesMenus.FlashSalesPlan, + l["Menu:FlashSalesPlan"], + "/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan" + ) + ); + } + + if (await context.IsGrantedAsync(FlashSalesPermissions.FlashSalesResult.Default)) + { + flashSalesManagementMenuItem.AddItem( + new ApplicationMenuItem( + FlashSalesMenus.FlashSalesResult, + l["Menu:FlashSalesResult"], + "/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult" + ) + ); + } + + if (!flashSalesManagementMenuItem.Items.IsNullOrEmpty()) + { + var eShopMenuItem = context.Menu.Items.GetOrAdd(i => i.Name == FlashSalesMenus.ModuleGroupPrefix, + () => new ApplicationMenuItem(FlashSalesMenus.ModuleGroupPrefix, l["Menu:EasyAbpEShop"], icon: "fa fa-shopping-bag")); + + eShopMenuItem.Items.Add(flashSalesManagementMenuItem); + } } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Menus/FlashSalesMenus.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Menus/FlashSalesMenus.cs index 9faa7e22..cad519a2 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Menus/FlashSalesMenus.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Menus/FlashSalesMenus.cs @@ -1,10 +1,12 @@ -namespace EasyAbp.EShop.Plugins.FlashSales.Web.Menus; +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Menus; -public class FlashSalesMenus +public static class FlashSalesMenus { - public const string Prefix = "FlashSales"; + public const string ModuleGroupPrefix = "EasyAbp.EShop"; - //Add your menu items here... - //public const string Home = Prefix + ".MyNewMenuItem"; + public const string Prefix = ModuleGroupPrefix + ".Plugins.FlashSales"; + public const string FlashSalesPlan = Prefix + ".FlashSalesPlan"; + + public const string FlashSalesResult = Prefix + ".FlashSalesResult"; } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/CreateModal.cshtml b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/CreateModal.cshtml new file mode 100644 index 00000000..32a1aa21 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/CreateModal.cshtml @@ -0,0 +1,21 @@ +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using EasyAbp.EShop.Plugins.FlashSales.Localization +@using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan + +@inject IHtmlLocalizer L +@model CreateModalModel +@{ + Layout = null; +} + + + + + + + + + + \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/CreateModal.cshtml.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/CreateModal.cshtml.cs new file mode 100644 index 00000000..760d498a --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/CreateModal.cshtml.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; +using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan.ViewModels; +using Microsoft.AspNetCore.Mvc; + +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan; + +public class CreateModalModel : FlashSalesPageModel +{ + [BindProperty] + public CreateFlashSalesPlanViewModel ViewModel { get; set; } + + protected IFlashSalesPlanAppService Service { get; } + + public CreateModalModel(IFlashSalesPlanAppService service) + { + Service = service; + } + + public virtual async Task OnPostAsync() + { + var dto = ObjectMapper.Map(ViewModel); + await Service.CreateAsync(dto); + return NoContent(); + } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/EditModal.cshtml b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/EditModal.cshtml new file mode 100644 index 00000000..faa6ffc9 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/EditModal.cshtml @@ -0,0 +1,22 @@ +@page +@using EasyAbp.EShop.Plugins.FlashSales.Localization +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan + +@inject IHtmlLocalizer L +@model EditModalModel +@{ + Layout = null; +} + + + + + + + + + + + diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/EditModal.cshtml.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/EditModal.cshtml.cs new file mode 100644 index 00000000..faa49dd3 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/EditModal.cshtml.cs @@ -0,0 +1,38 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; +using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan.ViewModels; + +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan; + +public class EditModalModel : FlashSalesPageModel +{ + [HiddenInput] + [BindProperty(SupportsGet = true)] + public Guid Id { get; set; } + + [BindProperty] + public EditFlashSalesPlanViewModel ViewModel { get; set; } + + protected IFlashSalesPlanAppService Service { get; } + + public EditModalModel(IFlashSalesPlanAppService service) + { + Service = service; + } + + public virtual async Task OnGetAsync() + { + var dto = await Service.GetAsync(Id); + ViewModel = ObjectMapper.Map(dto); + } + + public virtual async Task OnPostAsync() + { + var dto = ObjectMapper.Map(ViewModel); + await Service.UpdateAsync(Id, dto); + return NoContent(); + } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/Index.cshtml b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/Index.cshtml new file mode 100644 index 00000000..d96bb645 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/Index.cshtml @@ -0,0 +1,50 @@ +@page +@using EasyAbp.EShop.Plugins.FlashSales.Permissions +@using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Layout +@using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan +@using EasyAbp.EShop.Plugins.FlashSales.Localization +@using EasyAbp.EShop.Plugins.FlashSales.Web.Menus + +@model IndexModel + +@inject IPageLayout PageLayout +@inject IHtmlLocalizer L +@inject IAuthorizationService Authorization +@{ + PageLayout.Content.Title = L["FlashSalesPlan"].Value; + PageLayout.Content.BreadCrumb.Add(L["Menu:FlashSalesPlan"].Value); + PageLayout.Content.MenuItemName = FlashSalesMenus.FlashSalesPlan; +} + +@section scripts +{ + +} +@section styles +{ + +} + + + + + + @L["FlashSalesPlan"] + + + @if (await Authorization.IsGrantedAsync(FlashSalesPermissions.FlashSalesPlan.Create)) + { + + } + + + + + + + diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/Index.cshtml.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/Index.cshtml.cs new file mode 100644 index 00000000..2203fdef --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/Index.cshtml.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan; + +public class IndexModel : FlashSalesPageModel +{ + public virtual async Task OnGetAsync() + { + await Task.CompletedTask; + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/CreateFlashSalesPlanViewModel.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/CreateFlashSalesPlanViewModel.cs new file mode 100644 index 00000000..d65ae9bb --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/CreateFlashSalesPlanViewModel.cs @@ -0,0 +1,25 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan.ViewModels; + +public class CreateFlashSalesPlanViewModel +{ + [Display(Name = "FlashSalesPlanStoreId")] + public Guid StoreId { get; set; } + + [Display(Name = "FlashSalesPlanBeginTime")] + public DateTime BeginTime { get; set; } + + [Display(Name = "FlashSalesPlanEndTime")] + public DateTime EndTime { get; set; } + + [Display(Name = "FlashSalesPlanProductId")] + public Guid ProductId { get; set; } + + [Display(Name = "FlashSalesPlanProductSkuId")] + public Guid ProductSkuId { get; set; } + + [Display(Name = "FlashSalesPlanIsPublished")] + public bool IsPublished { get; set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/EditFlashSalesPlanViewModel.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/EditFlashSalesPlanViewModel.cs new file mode 100644 index 00000000..972d0980 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/EditFlashSalesPlanViewModel.cs @@ -0,0 +1,33 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; +using Volo.Abp.Domain.Entities; + +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesPlans.FlashSalesPlan.ViewModels; + +public class EditFlashSalesPlanViewModel : IHasConcurrencyStamp +{ + [DisabledInput] + [ReadOnlyInput] + [Display(Name = "FlashSalesPlanStoreId")] + public Guid StoreId { get; set; } + + [Display(Name = "FlashSalesPlanBeginTime")] + public DateTime BeginTime { get; set; } + + [Display(Name = "FlashSalesPlanEndTime")] + public DateTime EndTime { get; set; } + + [Display(Name = "FlashSalesPlanProductId")] + public Guid ProductId { get; set; } + + [Display(Name = "FlashSalesPlanProductSkuId")] + public Guid ProductSkuId { get; set; } + + [Display(Name = "FlashSalesPlanIsPublished")] + public bool IsPublished { get; set; } + + [HiddenInput] + public string ConcurrencyStamp { get; set; } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/index.css b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/index.css new file mode 100644 index 00000000..e69de29b diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/index.js b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/index.js new file mode 100644 index 00000000..8b4a951e --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/index.js @@ -0,0 +1,87 @@ +$(function () { + + var l = abp.localization.getResource('EasyAbpEShopPluginsFlashSales'); + + var service = easyAbp.eShop.plugins.flashSales.flashSalesPlans.flashSalesPlan; + var createModal = new abp.ModalManager(abp.appPath + 'EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/CreateModal'); + var editModal = new abp.ModalManager(abp.appPath + 'EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/EditModal'); + + var dataTable = $('#FlashSalesPlanTable').DataTable(abp.libs.datatables.normalizeConfiguration({ + processing: true, + serverSide: true, + paging: true, + searching: false, + autoWidth: false, + scrollCollapse: true, + order: [[2, "asc"]], + ajax: abp.libs.datatables.createAjax(service.getList), + columnDefs: [ + { + rowAction: { + items: + [ + { + text: l('Edit'), + visible: abp.auth.isGranted('EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlan.Update'), + action: function (data) { + editModal.open({ id: data.record.id }); + } + }, + { + text: l('Delete'), + visible: abp.auth.isGranted('EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlan.Delete'), + confirmMessage: function (data) { + return l('FlashSalesPlanDeletionConfirmationMessage', data.record.id); + }, + action: function (data) { + service.delete(data.record.id) + .then(function () { + abp.notify.info(l('SuccessfullyDeleted')); + dataTable.ajax.reload(); + }); + } + } + ] + } + }, + { + title: l('FlashSalesPlanStoreId'), + data: "storeId" + }, + { + title: l('FlashSalesPlanBeginTime'), + data: "beginTime" + }, + { + title: l('FlashSalesPlanEndTime'), + data: "endTime" + }, + { + title: l('FlashSalesPlanProductId'), + data: "productId" + }, + { + title: l('FlashSalesPlanProductSkuId'), + data: "productSkuId" + }, + { + title: l('FlashSalesPlanIsPublished'), + data: "isPublished", + dataFormat: 'boolean' + }, + ] + })); + + createModal.onResult(function () { + dataTable.ajax.reload(); + }); + + editModal.onResult(function () { + dataTable.ajax.reload(); + }); + + $('#NewFlashSalesPlanButton').click(function (e) { + e.preventDefault(); + createModal.open(); + }); +}); diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/Index.cshtml b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/Index.cshtml new file mode 100644 index 00000000..ba1d6a72 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/Index.cshtml @@ -0,0 +1,41 @@ +@page +@using EasyAbp.EShop.Plugins.FlashSales.Permissions +@using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Layout +@using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesResults.FlashSalesResult +@using EasyAbp.EShop.Plugins.FlashSales.Localization +@using EasyAbp.EShop.Plugins.FlashSales.Web.Menus + +@model IndexModel + +@inject IPageLayout PageLayout +@inject IHtmlLocalizer L +@inject IAuthorizationService Authorization +@{ + PageLayout.Content.Title = L["FlashSalesResult"].Value; + PageLayout.Content.BreadCrumb.Add(L["Menu:FlashSalesResult"].Value); + PageLayout.Content.MenuItemName = FlashSalesMenus.FlashSalesResult; +} + +@section scripts +{ + +} +@section styles +{ + +} + + + + + + @L["FlashSalesResult"] + + + + + + + diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/Index.cshtml.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/Index.cshtml.cs new file mode 100644 index 00000000..ae48fd64 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/Index.cshtml.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesResults.FlashSalesResult; + +public class IndexModel : PageModel +{ + public void OnGet() + { + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModal.cshtml b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModal.cshtml new file mode 100644 index 00000000..ef929eab --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModal.cshtml @@ -0,0 +1,22 @@ +@page +@using EasyAbp.EShop.Plugins.FlashSales.Localization +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesResults.FlashSalesResult + +@inject IHtmlLocalizer L +@model ViewModalModel +@{ + Layout = null; +} + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModal.cshtml.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModal.cshtml.cs new file mode 100644 index 00000000..9d5fa316 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModal.cshtml.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults.Dtos; +using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesResults.FlashSalesResult.ViewModels; +using Microsoft.AspNetCore.Mvc; + +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesResults.FlashSalesResult; + +public class ViewModalModel : FlashSalesPageModel +{ + [HiddenInput] + [BindProperty(SupportsGet = true)] + public Guid Id { get; set; } + + [BindProperty] + public ViewFlashSalesResultViewModel ViewModel { get; set; } + + protected IFlashSalesResultAppService Service { get; } + + public ViewModalModel(IFlashSalesResultAppService service) + { + Service = service; + } + + public virtual async Task OnGetAsync() + { + var dto = await Service.GetAsync(Id); + ViewModel = ObjectMapper.Map(dto); + } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModels/ViewFlashSalesResultViewModel.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModels/ViewFlashSalesResultViewModel.cs new file mode 100644 index 00000000..c72ba9f0 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModels/ViewFlashSalesResultViewModel.cs @@ -0,0 +1,23 @@ +using System; +using System.ComponentModel.DataAnnotations; +using EasyAbp.EShop.Plugins.FlashSales.FlashSalesResults; + +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.FlashSalesResults.FlashSalesResult.ViewModels; + +public class ViewFlashSalesResultViewModel +{ + [Display(Name = "FlashSalesResultStoreId")] + public virtual Guid StoreId { get; protected set; } + + [Display(Name = "FlashSalesResultPlanId")] + public virtual Guid PlanId { get; protected set; } + + [Display(Name = "FlashSalesResultStatus")] + public virtual FlashSalesResultStatus Status { get; protected set; } + + [Display(Name = "FlashSalesResultUserId")] + public virtual Guid UserId { get; protected set; } + + [Display(Name = "FlashSalesResultOrderId")] + public virtual Guid? OrderId { get; protected set; } +} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/index.css b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/index.css new file mode 100644 index 00000000..e69de29b diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/index.js b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/index.js new file mode 100644 index 00000000..d29f6825 --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/index.js @@ -0,0 +1,62 @@ +$(function () { + + var l = abp.localization.getResource('EasyAbpEShopPluginsFlashSales'); + + var service = easyAbp.eShop.plugins.flashSales.flashSalesPlans.flashSalesPlan; + var viewModal = new abp.ModalManager(abp.appPath + 'EShop/Plugins/FlashSales/FlashSalesResults/FlashSalesResult/ViewModal'); + + var dataTable = $('#FlashSalesResultTable').DataTable(abp.libs.datatables.normalizeConfiguration({ + processing: true, + serverSide: true, + paging: true, + searching: false, + autoWidth: false, + scrollCollapse: true, + order: [[6, "desc"]], + ajax: abp.libs.datatables.createAjax(service.getList), + columnDefs: [ + { + rowAction: { + items: + [ + { + text: l('ViewFlashSalesPlan'), + action: function (data) { + viewModal.open({ id: data.record.id }); + } + } + ] + } + }, + { + title: l('FlashSalesResultStoreId'), + data: "storeId" + }, + { + title: l('FlashSalesResultPlanId'), + data: "planId" + }, + { + title: l('FlashSalesResultStatus'), + data: "status" + }, + { + title: l('FlashSalesResultUserId'), + data: "userId" + }, + { + title: l('FlashSalesResultOrderId'), + data: "orderId" + }, + { + title: l('FlashSalesResultCreationTime'), + data: "creationTime", + dataFormat: 'datetime' + }, + ] + })); + + viewModal.onResult(function () { + dataTable.ajax.reload(); + }); +}); diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EasyAbp/EShop/Plugins/FlashSales/Index.cshtml b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/Index.cshtml similarity index 73% rename from plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EasyAbp/EShop/Plugins/FlashSales/Index.cshtml rename to plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/Index.cshtml index 4eb1c2d9..fed6c363 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EasyAbp/EShop/Plugins/FlashSales/Index.cshtml +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/Index.cshtml @@ -1,11 +1,12 @@ @page @using Microsoft.Extensions.Localization @using EasyAbp.EShop.Plugins.FlashSales.Localization -@using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EasyAbp.EShop.Plugins.FlashSales +@using EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales + @model IndexModel @inject IStringLocalizer L - @{ } +

FlashSales

@L["SamplePageMessage"]

diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EasyAbp/EShop/Plugins/FlashSales/Index.cshtml.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/Index.cshtml.cs similarity index 50% rename from plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EasyAbp/EShop/Plugins/FlashSales/Index.cshtml.cs rename to plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/Index.cshtml.cs index 7438e942..a4551d28 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EasyAbp/EShop/Plugins/FlashSales/Index.cshtml.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/Index.cshtml.cs @@ -1,4 +1,4 @@ -namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EasyAbp.EShop.Plugins.FlashSales; +namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales; public class IndexModel : FlashSalesPageModel { diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EasyAbp/EShop/Plugins/FlashSales/_ViewImports.cshtml b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/_ViewImports.cshtml similarity index 100% rename from plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EasyAbp/EShop/Plugins/FlashSales/_ViewImports.cshtml rename to plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/_ViewImports.cshtml