diff --git a/.editorconfig b/.editorconfig index 56d238d4..52a5b14d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,12 +3,24 @@ root = true [*] charset = utf-8 indent_style = space -indent_size = 4 +indent_size = 2 end_of_line = crlf trim_trailing_whitespace = true insert_final_newline = true -# Dotnet code style settings: +# Project files +[*.{csproj,props}] +insert_final_newline = false + +# HTML files +[*.{html,htm}] +insert_final_newline = false + +# Code +[*.{cs,js,ts,ps1,sh,bat,cmd}] +indent_size = 4 + +# Dotnet code style settings [*.{cs,vb}] # Sort using and Import directives with System.* appearing first @@ -24,16 +36,24 @@ dotnet_style_qualification_for_event = false:suggestion dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion dotnet_style_predefined_type_for_member_access = true:suggestion +# Use explicit accessibility modifiers +dotnet_style_require_accessibility_modifiers = true:suggestion + # Suggest more modern language features when available dotnet_style_object_initializer = true:suggestion dotnet_style_collection_initializer = true:suggestion dotnet_style_coalesce_expression = true:suggestion dotnet_style_null_propagation = true:suggestion dotnet_style_explicit_tuple_names = true:suggestion +dotnet_prefer_inferred_tuple_names = true:suggestion +dotnet_prefer_inferred_anonymous_type_member_names = true:suggestion -# CSharp code style settings: +# CSharp code style settings [*.cs] +# Prefer curly braces even for one line of code +csharp_prefer_braces = true:suggestion + # Prefer "var" everywhere csharp_style_var_for_built_in_types = true:suggestion csharp_style_var_when_type_is_apparent = true:suggestion @@ -55,6 +75,9 @@ csharp_style_pattern_matching_over_as_with_null_check = true:suggestion csharp_style_inlined_variable_declaration = true:suggestion csharp_style_throw_expression = true:suggestion csharp_style_conditional_delegate_call = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion # Newline settings csharp_new_line_before_open_brace = all @@ -63,12 +86,84 @@ csharp_new_line_before_catch = true csharp_new_line_before_finally = true csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true -#JSON code style settings -[*.json] -indent_style = space -indent_size = 2 +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_parentheses = false + +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent + +[*.{cs,vb}] +#### 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.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 + +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 -#HTML code style settings -[*.html] -insert_final_newline = false \ No newline at end of file +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_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion diff --git a/Directory.Build.props b/Directory.Build.props index debf9300..91faf8db 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,9 +1,12 @@ - + + 3.400.0 - - + $(VersionSuffix)-$(BuildNumber) + + true + diff --git a/VirtoCommerce.PricingModule.sln.DotSettings b/VirtoCommerce.PricingModule.sln.DotSettings new file mode 100644 index 00000000..08ce031a --- /dev/null +++ b/VirtoCommerce.PricingModule.sln.DotSettings @@ -0,0 +1,6 @@ + + True + True + True + True + diff --git a/module.ignore b/module.ignore new file mode 100644 index 00000000..cf886013 --- /dev/null +++ b/module.ignore @@ -0,0 +1,2 @@ +Antlr4.Runtime.Standard.dll +TimeZoneConverter.dll diff --git a/src/VirtoCommerce.PricingModule.Core/Model/PriceEvaluationContext.cs b/src/VirtoCommerce.PricingModule.Core/Model/PriceEvaluationContext.cs index 1eaeb3dc..7723b000 100644 --- a/src/VirtoCommerce.PricingModule.Core/Model/PriceEvaluationContext.cs +++ b/src/VirtoCommerce.PricingModule.Core/Model/PriceEvaluationContext.cs @@ -1,30 +1,31 @@ using System; +using System.Collections.Generic; using VirtoCommerce.CoreModule.Core.Common; namespace VirtoCommerce.PricingModule.Core.Model { - public class PriceEvaluationContext : EvaluationContextBase, ICloneable - { - public string StoreId { get; set; } - public string CatalogId { get; set; } - public string[] ProductIds { get; set; } + public class PriceEvaluationContext : EvaluationContextBase, ICloneable + { + public string StoreId { get; set; } + public string CatalogId { get; set; } + public IList ProductIds { get; set; } // The ordered list of price-list IDs, evaluation logic will return only matched product prices from the first price-list from this list // To return all the prices found, simply set ReturnAllMatchedPrices to true - public string[] PricelistIds { get; set; } - public Pricelist[] Pricelists { get; set; } + public IList PricelistIds { get; set; } + public IList Pricelists { get; set; } // Set this flag to true for return all matched prices from all given pricelists - public bool ReturnAllMatchedPrices { get; set; } + public bool ReturnAllMatchedPrices { get; set; } public decimal Quantity { get; set; } - public string CustomerId { get; set; } - public string OrganizationId { get; set; } - public DateTime? CertainDate { get; set; } - public string Currency { get; set; } + public string CustomerId { get; set; } + public string OrganizationId { get; set; } + public DateTime? CertainDate { get; set; } + public string Currency { get; set; } // Set this flag to true for indexing from all given pricelists and skip Dynamic Conditions except Start and End Date public bool SkipAssignmentValidation { get; set; } public object Clone() { - return base.MemberwiseClone() as PriceEvaluationContext; + return (PriceEvaluationContext)MemberwiseClone(); } } } diff --git a/src/VirtoCommerce.PricingModule.Core/Model/Search/MergedPriceSearchCriteria.cs b/src/VirtoCommerce.PricingModule.Core/Model/Search/MergedPriceSearchCriteria.cs index 567ad588..ef1b8e9d 100644 --- a/src/VirtoCommerce.PricingModule.Core/Model/Search/MergedPriceSearchCriteria.cs +++ b/src/VirtoCommerce.PricingModule.Core/Model/Search/MergedPriceSearchCriteria.cs @@ -11,6 +11,6 @@ public class MergedPriceSearchCriteria : SearchCriteriaBase public string PriorityPriceListId { get; set; } - public List ProductIds { get; set; } + public IList ProductIds { get; set; } } } diff --git a/src/VirtoCommerce.PricingModule.Core/Model/Search/PricelistAssignmentsSearchCriteria.cs b/src/VirtoCommerce.PricingModule.Core/Model/Search/PricelistAssignmentsSearchCriteria.cs index 53ef0488..db413642 100644 --- a/src/VirtoCommerce.PricingModule.Core/Model/Search/PricelistAssignmentsSearchCriteria.cs +++ b/src/VirtoCommerce.PricingModule.Core/Model/Search/PricelistAssignmentsSearchCriteria.cs @@ -1,13 +1,15 @@ +using System.Collections.Generic; + namespace VirtoCommerce.PricingModule.Core.Model.Search { public class PricelistAssignmentsSearchCriteria : PricingSearchCriteria { public string PriceListId { get; set; } - public string[] CatalogIds { get; set; } - public string[] StoreIds { get; set; } + public IList CatalogIds { get; set; } + public IList StoreIds { get; set; } - private string[] _priceListIds; - public string[] PriceListIds + private IList _priceListIds; + public IList PriceListIds { get { diff --git a/src/VirtoCommerce.PricingModule.Core/Model/Search/PricelistSearchCriteria.cs b/src/VirtoCommerce.PricingModule.Core/Model/Search/PricelistSearchCriteria.cs index 04310034..1baa2212 100644 --- a/src/VirtoCommerce.PricingModule.Core/Model/Search/PricelistSearchCriteria.cs +++ b/src/VirtoCommerce.PricingModule.Core/Model/Search/PricelistSearchCriteria.cs @@ -1,7 +1,9 @@ +using System.Collections.Generic; + namespace VirtoCommerce.PricingModule.Core.Model.Search { public class PricelistSearchCriteria : PricingSearchCriteria { - public string[] Currencies { get; set; } + public IList Currencies { get; set; } } } diff --git a/src/VirtoCommerce.PricingModule.Core/Model/Search/PricesSearchCriteria.cs b/src/VirtoCommerce.PricingModule.Core/Model/Search/PricesSearchCriteria.cs index 209a1eff..fcbf5a90 100644 --- a/src/VirtoCommerce.PricingModule.Core/Model/Search/PricesSearchCriteria.cs +++ b/src/VirtoCommerce.PricingModule.Core/Model/Search/PricesSearchCriteria.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace VirtoCommerce.PricingModule.Core.Model.Search { @@ -9,8 +10,8 @@ public class PricesSearchCriteria : PricingSearchCriteria public string PriceListId { get; set; } - private string[] _priceListIds; - public string[] PriceListIds + private IList _priceListIds; + public IList PriceListIds { get { @@ -28,8 +29,8 @@ public string[] PriceListIds public string ProductId { get; set; } - private string[] _productIds; - public string[] ProductIds + private IList _productIds; + public IList ProductIds { get { diff --git a/src/VirtoCommerce.PricingModule.Core/Model/Search/PricingSearchResult.cs b/src/VirtoCommerce.PricingModule.Core/Model/Search/PricingSearchResult.cs deleted file mode 100644 index 2e3519d9..00000000 --- a/src/VirtoCommerce.PricingModule.Core/Model/Search/PricingSearchResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace VirtoCommerce.PricingModule.Core.Model.Search -{ - [Obsolete("This class is not used by PricingModule anymore. Please use GenericSearchResult instead.")] - public class PricingSearchResult - { - public int TotalCount { get; set; } - public ICollection Results { get; set; } - } -} diff --git a/src/VirtoCommerce.PricingModule.Core/Services/IPriceSearchService.cs b/src/VirtoCommerce.PricingModule.Core/Services/IPriceSearchService.cs new file mode 100644 index 00000000..a695ae72 --- /dev/null +++ b/src/VirtoCommerce.PricingModule.Core/Services/IPriceSearchService.cs @@ -0,0 +1,9 @@ +using VirtoCommerce.Platform.Core.GenericCrud; +using VirtoCommerce.PricingModule.Core.Model; +using VirtoCommerce.PricingModule.Core.Model.Search; + +namespace VirtoCommerce.PricingModule.Core.Services; + +public interface IPriceSearchService : ISearchService +{ +} diff --git a/src/VirtoCommerce.PricingModule.Core/Services/IPriceService.cs b/src/VirtoCommerce.PricingModule.Core/Services/IPriceService.cs new file mode 100644 index 00000000..5f131dfc --- /dev/null +++ b/src/VirtoCommerce.PricingModule.Core/Services/IPriceService.cs @@ -0,0 +1,8 @@ +using VirtoCommerce.Platform.Core.GenericCrud; +using VirtoCommerce.PricingModule.Core.Model; + +namespace VirtoCommerce.PricingModule.Core.Services; + +public interface IPriceService : ICrudService +{ +} diff --git a/src/VirtoCommerce.PricingModule.Core/Services/IPricelistAssignmentSearchService.cs b/src/VirtoCommerce.PricingModule.Core/Services/IPricelistAssignmentSearchService.cs new file mode 100644 index 00000000..f1308cd6 --- /dev/null +++ b/src/VirtoCommerce.PricingModule.Core/Services/IPricelistAssignmentSearchService.cs @@ -0,0 +1,9 @@ +using VirtoCommerce.Platform.Core.GenericCrud; +using VirtoCommerce.PricingModule.Core.Model; +using VirtoCommerce.PricingModule.Core.Model.Search; + +namespace VirtoCommerce.PricingModule.Core.Services; + +public interface IPricelistAssignmentSearchService : ISearchService +{ +} diff --git a/src/VirtoCommerce.PricingModule.Core/Services/IPricelistAssignmentService.cs b/src/VirtoCommerce.PricingModule.Core/Services/IPricelistAssignmentService.cs new file mode 100644 index 00000000..9d9e2f10 --- /dev/null +++ b/src/VirtoCommerce.PricingModule.Core/Services/IPricelistAssignmentService.cs @@ -0,0 +1,8 @@ +using VirtoCommerce.Platform.Core.GenericCrud; +using VirtoCommerce.PricingModule.Core.Model; + +namespace VirtoCommerce.PricingModule.Core.Services; + +public interface IPricelistAssignmentService : ICrudService +{ +} diff --git a/src/VirtoCommerce.PricingModule.Core/Services/IPricelistSearchService.cs b/src/VirtoCommerce.PricingModule.Core/Services/IPricelistSearchService.cs new file mode 100644 index 00000000..41b8b73e --- /dev/null +++ b/src/VirtoCommerce.PricingModule.Core/Services/IPricelistSearchService.cs @@ -0,0 +1,9 @@ +using VirtoCommerce.Platform.Core.GenericCrud; +using VirtoCommerce.PricingModule.Core.Model; +using VirtoCommerce.PricingModule.Core.Model.Search; + +namespace VirtoCommerce.PricingModule.Core.Services; + +public interface IPricelistSearchService : ISearchService +{ +} diff --git a/src/VirtoCommerce.PricingModule.Core/Services/IPricelistService.cs b/src/VirtoCommerce.PricingModule.Core/Services/IPricelistService.cs new file mode 100644 index 00000000..f3f74ef0 --- /dev/null +++ b/src/VirtoCommerce.PricingModule.Core/Services/IPricelistService.cs @@ -0,0 +1,8 @@ +using VirtoCommerce.Platform.Core.GenericCrud; +using VirtoCommerce.PricingModule.Core.Model; + +namespace VirtoCommerce.PricingModule.Core.Services; + +public interface IPricelistService : ICrudService +{ +} diff --git a/src/VirtoCommerce.PricingModule.Core/Services/IPricingEvaluatorService.cs b/src/VirtoCommerce.PricingModule.Core/Services/IPricingEvaluatorService.cs index 05ef7d85..7680433d 100644 --- a/src/VirtoCommerce.PricingModule.Core/Services/IPricingEvaluatorService.cs +++ b/src/VirtoCommerce.PricingModule.Core/Services/IPricingEvaluatorService.cs @@ -11,7 +11,7 @@ public interface IPricingEvaluatorService /// /// /// - Task> EvaluatePriceListsAsync(PriceEvaluationContext evalContext); + Task> EvaluatePriceListsAsync(PriceEvaluationContext evalContext); /// /// Evaluation product prices. @@ -19,6 +19,6 @@ public interface IPricingEvaluatorService /// /// /// - Task> EvaluateProductPricesAsync(PriceEvaluationContext evalContext); + Task> EvaluateProductPricesAsync(PriceEvaluationContext evalContext); } } diff --git a/src/VirtoCommerce.PricingModule.Core/Services/IPricingSearchService.cs b/src/VirtoCommerce.PricingModule.Core/Services/IPricingSearchService.cs deleted file mode 100644 index 0c4c447f..00000000 --- a/src/VirtoCommerce.PricingModule.Core/Services/IPricingSearchService.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Threading.Tasks; -using VirtoCommerce.PricingModule.Core.Model.Search; - -namespace VirtoCommerce.PricingModule.Core.Services -{ - [Obsolete("Use separate interfaces: ISearchService, " + - "ISearchService, " + - "ISearchService")] - public interface IPricingSearchService - { - Task SearchPricesAsync(PricesSearchCriteria criteria); - Task SearchPricelistsAsync(PricelistSearchCriteria criteria); - Task SearchPricelistAssignmentsAsync(PricelistAssignmentsSearchCriteria criteria); - } -} diff --git a/src/VirtoCommerce.PricingModule.Core/Services/IPricingService.cs b/src/VirtoCommerce.PricingModule.Core/Services/IPricingService.cs deleted file mode 100644 index 7a12a8e3..00000000 --- a/src/VirtoCommerce.PricingModule.Core/Services/IPricingService.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using VirtoCommerce.PricingModule.Core.Model; - -namespace VirtoCommerce.PricingModule.Core.Services -{ - [Obsolete("Interface was decoupled to IPricingEvaluatorService, ICrudService, ICrudService, ICrudService")] - public interface IPricingService - { - Task GetPricesByIdAsync(string[] ids); - Task GetPricelistsByIdAsync(string[] ids, string responseGroup = null); - Task GetPricelistAssignmentsByIdAsync(string[] ids); - - Task SavePricesAsync(Price[] prices); - Task SavePricelistsAsync(Pricelist[] priceLists); - Task SavePricelistAssignmentsAsync(PricelistAssignment[] assignments); - - Task DeletePricelistsAsync(string[] ids); - Task DeletePricesAsync(string[] ids); - Task DeletePricelistsAssignmentsAsync(string[] ids); - - /// - /// Evaluate pricelists for special context. All resulting pricelists ordered by priority - /// - /// - /// - Task> EvaluatePriceListsAsync(PriceEvaluationContext evalContext); - - /// - /// Evaluation product prices. - /// Will get either all prices or one price per currency depending on the settings in evalContext. - /// - /// - /// - Task> EvaluateProductPricesAsync(PriceEvaluationContext evalContext); - } -} diff --git a/src/VirtoCommerce.PricingModule.Core/VirtoCommerce.PricingModule.Core.csproj b/src/VirtoCommerce.PricingModule.Core/VirtoCommerce.PricingModule.Core.csproj index 65bb55f4..8ad1909d 100644 --- a/src/VirtoCommerce.PricingModule.Core/VirtoCommerce.PricingModule.Core.csproj +++ b/src/VirtoCommerce.PricingModule.Core/VirtoCommerce.PricingModule.Core.csproj @@ -1,22 +1,22 @@ - - net6.0 - true - 1591 - True - true - true - true - snupkg - - - - false - - - - - - - + + net6.0 + true + 1591 + True + true + true + true + snupkg + + + + false + + + + + + + \ No newline at end of file diff --git a/src/VirtoCommerce.PricingModule.Data.MySql/VirtoCommerce.PricingModule.Data.MySql.csproj b/src/VirtoCommerce.PricingModule.Data.MySql/VirtoCommerce.PricingModule.Data.MySql.csproj index 3574dfe1..08f37c0d 100644 --- a/src/VirtoCommerce.PricingModule.Data.MySql/VirtoCommerce.PricingModule.Data.MySql.csproj +++ b/src/VirtoCommerce.PricingModule.Data.MySql/VirtoCommerce.PricingModule.Data.MySql.csproj @@ -1,21 +1,17 @@ - net6.0 enable enable - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - diff --git a/src/VirtoCommerce.PricingModule.Data.PostgreSql/VirtoCommerce.PricingModule.Data.PostgreSql.csproj b/src/VirtoCommerce.PricingModule.Data.PostgreSql/VirtoCommerce.PricingModule.Data.PostgreSql.csproj index 62476291..65661c7d 100644 --- a/src/VirtoCommerce.PricingModule.Data.PostgreSql/VirtoCommerce.PricingModule.Data.PostgreSql.csproj +++ b/src/VirtoCommerce.PricingModule.Data.PostgreSql/VirtoCommerce.PricingModule.Data.PostgreSql.csproj @@ -1,22 +1,18 @@ - net6.0 enable enable - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - diff --git a/src/VirtoCommerce.PricingModule.Data.SqlServer/VirtoCommerce.PricingModule.Data.SqlServer.csproj b/src/VirtoCommerce.PricingModule.Data.SqlServer/VirtoCommerce.PricingModule.Data.SqlServer.csproj index ceb5c120..dc6697cf 100644 --- a/src/VirtoCommerce.PricingModule.Data.SqlServer/VirtoCommerce.PricingModule.Data.SqlServer.csproj +++ b/src/VirtoCommerce.PricingModule.Data.SqlServer/VirtoCommerce.PricingModule.Data.SqlServer.csproj @@ -1,21 +1,17 @@ - net6.0 enable enable - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - diff --git a/src/VirtoCommerce.PricingModule.Data/Common/ModuleConfigurator.cs b/src/VirtoCommerce.PricingModule.Data/Common/ModuleConfigurator.cs index cda955f6..d6760e2d 100644 --- a/src/VirtoCommerce.PricingModule.Data/Common/ModuleConfigurator.cs +++ b/src/VirtoCommerce.PricingModule.Data/Common/ModuleConfigurator.cs @@ -30,10 +30,7 @@ public async Task ConfigureSearchAsync() // Add or remove price document source to catalog product indexing configuration foreach (var configuration in _documentIndexingConfigurations.Where(c => c.DocumentType == KnownDocumentTypes.Product)) { - if (configuration.RelatedSources == null) - { - configuration.RelatedSources = new List(); - } + configuration.RelatedSources ??= new List(); var oldSource = configuration.RelatedSources.FirstOrDefault(x => x.ChangesProvider.GetType() == _changesProvider.GetType() && x.DocumentBuilder.GetType() == _priceDocumentBuilder.GetType()); if (oldSource != null) @@ -41,7 +38,7 @@ public async Task ConfigureSearchAsync() configuration.RelatedSources.Remove(oldSource); } - var priceIndexingEnabled = await _settingsManager.GetValueAsync(Core.ModuleConstants.Settings.General.PricingIndexing.Name, true); + var priceIndexingEnabled = await _settingsManager.GetValueAsync(Core.ModuleConstants.Settings.General.PricingIndexing); if (priceIndexingEnabled) { var productPriceDocumentSource = new IndexDocumentSource diff --git a/src/VirtoCommerce.PricingModule.Data/ExportImport/PricingExportImport.cs b/src/VirtoCommerce.PricingModule.Data/ExportImport/PricingExportImport.cs index af724077..3f5ac78c 100644 --- a/src/VirtoCommerce.PricingModule.Data/ExportImport/PricingExportImport.cs +++ b/src/VirtoCommerce.PricingModule.Data/ExportImport/PricingExportImport.cs @@ -1,13 +1,11 @@ using System; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.ExportImport; using VirtoCommerce.Platform.Core.Settings; -using VirtoCommerce.Platform.Data.ExportImport; using VirtoCommerce.PricingModule.Core; using VirtoCommerce.PricingModule.Core.Model; using VirtoCommerce.PricingModule.Core.Model.Search; @@ -17,19 +15,34 @@ namespace VirtoCommerce.PricingModule.Data.ExportImport { public sealed class PricingExportImport { - private readonly IPricingService _pricingService; - private readonly IPricingSearchService _pricingSearchService; + private readonly IPriceSearchService _priceSearchService; + private readonly IPriceService _priceService; + private readonly IPricelistSearchService _pricelistSearchService; + private readonly IPricelistService _pricelistService; + private readonly IPricelistAssignmentSearchService _pricelistAssignmentSearchService; + private readonly IPricelistAssignmentService _pricelistAssignmentService; private readonly ISettingsManager _settingsManager; private readonly JsonSerializer _jsonSerializer; private int? _batchSize; - public PricingExportImport(IPricingService pricingService, IPricingSearchService pricingSearchService, ISettingsManager settingsManager, JsonSerializer jsonSerializer) + public PricingExportImport( + IPriceSearchService priceSearchService, + IPriceService priceService, + IPricelistSearchService pricelistSearchService, + IPricelistService pricelistService, + IPricelistAssignmentSearchService pricelistAssignmentSearchService, + IPricelistAssignmentService pricelistAssignmentService, + ISettingsManager settingsManager, + JsonSerializer jsonSerializer) { - _pricingService = pricingService; - _pricingSearchService = pricingSearchService; + _priceSearchService = priceSearchService; + _priceService = priceService; + _pricelistSearchService = pricelistSearchService; + _pricelistService = pricelistService; + _pricelistAssignmentSearchService = pricelistAssignmentSearchService; + _pricelistAssignmentService = pricelistAssignmentService; _settingsManager = settingsManager; - _jsonSerializer = jsonSerializer; } @@ -37,10 +50,7 @@ private int BatchSize { get { - if (_batchSize == null) - { - _batchSize = _settingsManager.GetValue(ModuleConstants.Settings.General.ExportImportPageSize.Name, 50); - } + _batchSize ??= _settingsManager.GetValue(ModuleConstants.Settings.General.ExportImportPageSize); return (int)_batchSize; } @@ -65,11 +75,11 @@ public async Task DoExportAsync(Stream backupStream, Action - (GenericSearchResult)await _pricingSearchService.SearchPricelistsAsync(new PricelistSearchCriteria { Skip = skip, Take = take }) + await writer.SerializeArrayWithPagingAsync(_jsonSerializer, BatchSize, async (skip, take) => + (GenericSearchResult)await _pricelistSearchService.SearchNoCloneAsync(new PricelistSearchCriteria { Skip = skip, Take = take }) , (processedCount, totalCount) => { - progressInfo.Description = $"{ processedCount } of { totalCount } pricelits have been exported"; + progressInfo.Description = $"{processedCount} of {totalCount} pricelists have been exported"; progressCallback(progressInfo); }, cancellationToken); @@ -79,11 +89,11 @@ await writer.SerializeJsonArrayWithPagingAsync(_jsonSerializer, BatchSize, async await writer.WritePropertyNameAsync("Assignments"); - await writer.SerializeJsonArrayWithPagingAsync(_jsonSerializer, BatchSize, async (skip, take) => - (GenericSearchResult)await _pricingSearchService.SearchPricelistAssignmentsAsync(new PricelistAssignmentsSearchCriteria { Skip = skip, Take = take }) + await writer.SerializeArrayWithPagingAsync(_jsonSerializer, BatchSize, async (skip, take) => + (GenericSearchResult)await _pricelistAssignmentSearchService.SearchNoCloneAsync(new PricelistAssignmentsSearchCriteria { Skip = skip, Take = take }) , (processedCount, totalCount) => { - progressInfo.Description = $"{ processedCount } of { totalCount } pricelits assignments have been exported"; + progressInfo.Description = $"{processedCount} of {totalCount} pricelist assignments have been exported"; progressCallback(progressInfo); }, cancellationToken); @@ -93,11 +103,11 @@ await writer.SerializeJsonArrayWithPagingAsync(_jsonSerializer, BatchSize, async await writer.WritePropertyNameAsync("Prices"); - await writer.SerializeJsonArrayWithPagingAsync(_jsonSerializer, BatchSize, async (skip, take) => - (GenericSearchResult)await _pricingSearchService.SearchPricesAsync(new PricesSearchCriteria { Skip = skip, Take = take }) + await writer.SerializeArrayWithPagingAsync(_jsonSerializer, BatchSize, async (skip, take) => + (GenericSearchResult)await _priceSearchService.SearchNoCloneAsync(new PricesSearchCriteria { Skip = skip, Take = take }) , (processedCount, totalCount) => { - progressInfo.Description = $"{ processedCount } of { totalCount } prices have been exported"; + progressInfo.Description = $"{processedCount} of {totalCount} prices have been exported"; progressCallback(progressInfo); }, cancellationToken); @@ -117,7 +127,7 @@ public async Task DoImportAsync(Stream stream, Action using (var streamReader = new StreamReader(stream)) using (var reader = new JsonTextReader(streamReader)) { - while (reader.Read()) + while (await reader.ReadAsync()) { if (reader.TokenType == JsonToken.PropertyName) { @@ -125,15 +135,15 @@ public async Task DoImportAsync(Stream stream, Action if (readerValue == "Pricelists") { - await reader.DeserializeJsonArrayWithPagingAsync(_jsonSerializer, BatchSize, items => _pricingService.SavePricelistsAsync(items.ToArray()), processedCount => + await reader.DeserializeArrayWithPagingAsync(_jsonSerializer, BatchSize, _pricelistService.SaveChangesAsync, processedCount => { - progressInfo.Description = $"{ processedCount } price lists have been imported"; + progressInfo.Description = $"{processedCount} price lists have been imported"; progressCallback(progressInfo); }, cancellationToken); } else if (readerValue == "Prices") { - await reader.DeserializeJsonArrayWithPagingAsync(_jsonSerializer, BatchSize, items => _pricingService.SavePricesAsync(items.ToArray()), processedCount => + await reader.DeserializeArrayWithPagingAsync(_jsonSerializer, BatchSize, _priceService.SaveChangesAsync, processedCount => { progressInfo.Description = $"Prices: {progressInfo.ProcessedCount} have been imported"; progressCallback(progressInfo); @@ -141,7 +151,7 @@ await reader.DeserializeJsonArrayWithPagingAsync(_jsonSerializer, BatchSi } else if (readerValue == "Assignments") { - await reader.DeserializeJsonArrayWithPagingAsync(_jsonSerializer, BatchSize, items => _pricingService.SavePricelistAssignmentsAsync(items.ToArray()), processedCount => + await reader.DeserializeArrayWithPagingAsync(_jsonSerializer, BatchSize, _pricelistAssignmentService.SaveChangesAsync, processedCount => { progressInfo.Description = $"{progressInfo.ProcessedCount} assignments have been imported"; progressCallback(progressInfo); diff --git a/src/VirtoCommerce.PricingModule.Data/ExportImport2/PriceExportPagedDataSource.cs b/src/VirtoCommerce.PricingModule.Data/ExportImport2/PriceExportPagedDataSource.cs index 66fde28f..7941e866 100644 --- a/src/VirtoCommerce.PricingModule.Data/ExportImport2/PriceExportPagedDataSource.cs +++ b/src/VirtoCommerce.PricingModule.Data/ExportImport2/PriceExportPagedDataSource.cs @@ -14,21 +14,25 @@ namespace VirtoCommerce.PricingModule.Data.ExportImport { public class PriceExportPagedDataSource : ExportPagedDataSource { - private readonly IPricingSearchService _searchService; - private readonly IPricingService _pricingService; + private readonly IPriceSearchService _priceSearchService; + private readonly IPriceService _priceService; + private readonly IPricelistService _pricelistService; private readonly IItemService _itemService; private readonly PriceExportDataQuery _dataQuery; public PriceExportPagedDataSource( - IPricingSearchService searchService, - IPricingService pricingService, - IItemService itemService, - PriceExportDataQuery dataQuery) : base(dataQuery) + PriceExportDataQuery dataQuery, + IPriceSearchService priceSearchService, + IPriceService priceService, + IPricelistService pricelistService, + IItemService itemService) + : base(dataQuery) { - _searchService = searchService; - _pricingService = pricingService; - _itemService = itemService; _dataQuery = dataQuery; + _priceSearchService = priceSearchService; + _priceService = priceService; + _pricelistService = pricelistService; + _itemService = itemService; } @@ -46,18 +50,18 @@ protected override PricesSearchCriteria BuildSearchCriteria(PriceExportDataQuery protected override ExportableSearchResult FetchData(PricesSearchCriteria searchCriteria) { - Price[] result; + IList result; int totalCount; if (searchCriteria.ObjectIds.Any(x => !string.IsNullOrWhiteSpace(x))) { - result = _pricingService.GetPricesByIdAsync(Enumerable.ToArray(searchCriteria.ObjectIds)).GetAwaiter().GetResult(); - totalCount = result.Length; + result = _priceService.GetNoCloneAsync(searchCriteria.ObjectIds).GetAwaiter().GetResult(); + totalCount = result.Count; } else { - var priceSearchResult = _searchService.SearchPricesAsync(searchCriteria).GetAwaiter().GetResult(); - result = priceSearchResult.Results.ToArray(); + var priceSearchResult = _priceSearchService.SearchNoCloneAsync(searchCriteria).GetAwaiter().GetResult(); + result = priceSearchResult.Results; totalCount = priceSearchResult.TotalCount; } @@ -85,15 +89,15 @@ protected virtual void FillAdditionalProperties(Dictionary x.ProductId).Distinct().ToArray(); var pricelistIds = models.Select(x => x.PricelistId).Distinct().ToArray(); - var products = _itemService.GetByIdsAsync(productIds, ItemResponseGroup.ItemInfo.ToString()).GetAwaiter().GetResult(); - var pricelists = _pricingService.GetPricelistsByIdAsync(pricelistIds).GetAwaiter().GetResult(); + var products = _itemService.GetNoCloneAsync(productIds, ItemResponseGroup.ItemInfo.ToString()).GetAwaiter().GetResult(); + var pricelists = _pricelistService.GetNoCloneAsync(pricelistIds).GetAwaiter().GetResult(); foreach (var kvp in viewableMap) { var model = kvp.Key; var viewableEntity = kvp.Value; - var product = products.FirstOrDefault(x => x.Id == model.ProductId); - var pricelist = pricelists.FirstOrDefault(x => x.Id == model.PricelistId); + var product = products?.FirstOrDefault(x => x.Id == model.ProductId); + var pricelist = pricelists?.FirstOrDefault(x => x.Id == model.PricelistId); viewableEntity.Code = product?.Code; viewableEntity.ImageUrl = product?.ImgSrc; diff --git a/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricelistAssignmentExportPagedDataSource.cs b/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricelistAssignmentExportPagedDataSource.cs index 91de81a5..a53be04a 100644 --- a/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricelistAssignmentExportPagedDataSource.cs +++ b/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricelistAssignmentExportPagedDataSource.cs @@ -14,21 +14,25 @@ namespace VirtoCommerce.PricingModule.Data.ExportImport { public class PricelistAssignmentExportPagedDataSource : ExportPagedDataSource { - private readonly IPricingSearchService _searchService; - private readonly IPricingService _pricingService; + private readonly IPricelistAssignmentSearchService _pricelistAssignmentSearchService; + private readonly IPricelistAssignmentService _pricelistAssignmentService; + private readonly IPricelistService _pricelistService; private readonly ICatalogService _catalogService; private readonly PricelistAssignmentExportDataQuery _dataQuery; public PricelistAssignmentExportPagedDataSource( - IPricingSearchService searchService, - IPricingService pricingService, - ICatalogService catalogService, - PricelistAssignmentExportDataQuery dataQuery) : base(dataQuery) + PricelistAssignmentExportDataQuery dataQuery, + IPricelistAssignmentSearchService pricelistAssignmentSearchService, + IPricelistAssignmentService pricelistAssignmentService, + IPricelistService pricelistService, + ICatalogService catalogService) + : base(dataQuery) { - _searchService = searchService; - _pricingService = pricingService; - _catalogService = catalogService; _dataQuery = dataQuery; + _pricelistAssignmentSearchService = pricelistAssignmentSearchService; + _pricelistAssignmentService = pricelistAssignmentService; + _pricelistService = pricelistService; + _catalogService = catalogService; } protected override PricelistAssignmentsSearchCriteria BuildSearchCriteria(PricelistAssignmentExportDataQuery exportDataQuery) @@ -44,18 +48,18 @@ protected override PricelistAssignmentsSearchCriteria BuildSearchCriteria(Pricel protected override ExportableSearchResult FetchData(PricelistAssignmentsSearchCriteria searchCriteria) { - PricelistAssignment[] result; + IList result; int totalCount; if (searchCriteria.ObjectIds.Any(x => !string.IsNullOrWhiteSpace(x))) { - result = _pricingService.GetPricelistAssignmentsByIdAsync(Enumerable.ToArray(searchCriteria.ObjectIds)).GetAwaiter().GetResult(); - totalCount = result.Length; + result = _pricelistAssignmentService.GetNoCloneAsync(searchCriteria.ObjectIds).GetAwaiter().GetResult(); + totalCount = result.Count; } else { - var pricelistAssignmentSearchResult = _searchService.SearchPricelistAssignmentsAsync(searchCriteria).GetAwaiter().GetResult(); - result = pricelistAssignmentSearchResult.Results.ToArray(); + var pricelistAssignmentSearchResult = _pricelistAssignmentSearchService.SearchNoCloneAsync(searchCriteria).GetAwaiter().GetResult(); + result = pricelistAssignmentSearchResult.Results; totalCount = pricelistAssignmentSearchResult.TotalCount; } @@ -84,15 +88,15 @@ protected virtual void FillAdditionalProperties(Dictionary x.CatalogId).Distinct().ToArray(); var pricelistIds = models.Select(x => x.PricelistId).Distinct().ToArray(); - var catalogs = _catalogService.GetByIdsAsync(catalogIds, CatalogResponseGroup.Info.ToString()).GetAwaiter().GetResult(); - var pricelists = _pricingService.GetPricelistsByIdAsync(pricelistIds).GetAwaiter().GetResult(); + var catalogs = _catalogService.GetNoCloneAsync(catalogIds, CatalogResponseGroup.Info.ToString()).GetAwaiter().GetResult(); + var pricelists = _pricelistService.GetNoCloneAsync(pricelistIds).GetAwaiter().GetResult(); foreach (var kvp in viewableMap) { var model = kvp.Key; var viewableEntity = kvp.Value; - var catalog = catalogs.FirstOrDefault(x => x.Id == model.CatalogId); - var pricelist = pricelists.FirstOrDefault(x => x.Id == model.PricelistId); + var catalog = catalogs?.FirstOrDefault(x => x.Id == model.CatalogId); + var pricelist = pricelists?.FirstOrDefault(x => x.Id == model.PricelistId); viewableEntity.CatalogName = catalog?.Name; viewableEntity.PricelistName = pricelist?.Name; diff --git a/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricelistExportPagedDataSource.cs b/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricelistExportPagedDataSource.cs index 10fac313..f7029270 100644 --- a/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricelistExportPagedDataSource.cs +++ b/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricelistExportPagedDataSource.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Linq; using VirtoCommerce.ExportModule.Core.Model; using VirtoCommerce.ExportModule.Data.Services; @@ -10,18 +11,19 @@ namespace VirtoCommerce.PricingModule.Data.ExportImport { public class PricelistExportPagedDataSource : ExportPagedDataSource { - private readonly IPricingSearchService _searchService; - private readonly IPricingService _pricingService; + private readonly IPricelistSearchService _pricelistSearchService; + private readonly IPricelistService _pricelistService; private readonly PricelistExportDataQuery _dataQuery; public PricelistExportPagedDataSource( - IPricingSearchService searchService, - IPricingService pricingService, - PricelistExportDataQuery dataQuery) : base(dataQuery) + PricelistExportDataQuery dataQuery, + IPricelistSearchService pricelistSearchService, + IPricelistService pricelistService) + : base(dataQuery) { - _searchService = searchService; - _pricingService = pricingService; _dataQuery = dataQuery; + _pricelistSearchService = pricelistSearchService; + _pricelistService = pricelistService; } protected override PricelistSearchCriteria BuildSearchCriteria(PricelistExportDataQuery exportDataQuery) @@ -36,22 +38,21 @@ protected override PricelistSearchCriteria BuildSearchCriteria(PricelistExportDa protected override ExportableSearchResult FetchData(PricelistSearchCriteria searchCriteria) { - Pricelist[] result; + IList result; int totalCount; if (searchCriteria.ObjectIds.Any(x => !string.IsNullOrWhiteSpace(x))) { - result = _pricingService.GetPricelistsByIdAsync(searchCriteria.ObjectIds.ToArray()).GetAwaiter().GetResult(); - totalCount = result.Length; + result = _pricelistService.GetNoCloneAsync(searchCriteria.ObjectIds).GetAwaiter().GetResult(); + totalCount = result.Count; } else { - var pricelistSearchResult = _searchService.SearchPricelistsAsync(searchCriteria).GetAwaiter().GetResult(); - result = pricelistSearchResult.Results.ToArray(); + var pricelistSearchResult = _pricelistSearchService.SearchNoCloneAsync(searchCriteria).GetAwaiter().GetResult(); + result = pricelistSearchResult.Results; totalCount = pricelistSearchResult.TotalCount; } - return new ExportableSearchResult() { Results = result.Select(x => (IExportable)AbstractTypeFactory.TryCreateInstance().FromModel(x)).ToList(), diff --git a/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricingExportPagedDataSourceFactory.cs b/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricingExportPagedDataSourceFactory.cs index fb172b1b..b996bea1 100644 --- a/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricingExportPagedDataSourceFactory.cs +++ b/src/VirtoCommerce.PricingModule.Data/ExportImport2/PricingExportPagedDataSourceFactory.cs @@ -7,15 +7,31 @@ namespace VirtoCommerce.PricingModule.Data.ExportImport { public class PricingExportPagedDataSourceFactory : IPricingExportPagedDataSourceFactory { - private readonly IPricingSearchService _searchService; - private readonly IPricingService _pricingService; + private readonly IPriceSearchService _priceSearchService; + private readonly IPriceService _priceService; + private readonly IPricelistSearchService _pricelistSearchService; + private readonly IPricelistService _pricelistService; + private readonly IPricelistAssignmentSearchService _pricelistAssignmentSearchService; + private readonly IPricelistAssignmentService _pricelistAssignmentService; private readonly IItemService _itemService; private readonly ICatalogService _catalogService; - public PricingExportPagedDataSourceFactory(IPricingSearchService searchService, IPricingService pricingService, IItemService itemService, ICatalogService catalogService) + public PricingExportPagedDataSourceFactory( + IPriceSearchService priceSearchService, + IPriceService priceService, + IPricelistSearchService pricelistSearchService, + IPricelistService pricelistService, + IPricelistAssignmentSearchService pricelistAssignmentSearchService, + IPricelistAssignmentService pricelistAssignmentService, + IItemService itemService, + ICatalogService catalogService) { - _searchService = searchService; - _pricingService = pricingService; + _priceSearchService = priceSearchService; + _priceService = priceService; + _pricelistSearchService = pricelistSearchService; + _pricelistService = pricelistService; + _pricelistAssignmentSearchService = pricelistAssignmentSearchService; + _pricelistAssignmentService = pricelistAssignmentService; _itemService = itemService; _catalogService = catalogService; } @@ -26,15 +42,15 @@ public virtual IPagedDataSource Create(ExportDataQuery dataQuery) if (dataQuery is PriceExportDataQuery priceExportDataQuery) { - result = new PriceExportPagedDataSource(_searchService, _pricingService, _itemService, priceExportDataQuery); + result = new PriceExportPagedDataSource(priceExportDataQuery, _priceSearchService, _priceService, _pricelistService, _itemService); } - else if (dataQuery is PricelistAssignmentExportDataQuery pricelistAssignmentExportDataQuery) + else if (dataQuery is PricelistExportDataQuery pricelistExportDataQuery) { - result = new PricelistAssignmentExportPagedDataSource(_searchService, _pricingService, _catalogService, pricelistAssignmentExportDataQuery); + result = new PricelistExportPagedDataSource(pricelistExportDataQuery, _pricelistSearchService, _pricelistService); } - else if (dataQuery is PricelistExportDataQuery pricelistExportDataQuery) + else if (dataQuery is PricelistAssignmentExportDataQuery pricelistAssignmentExportDataQuery) { - result = new PricelistExportPagedDataSource(_searchService, _pricingService, pricelistExportDataQuery); + result = new PricelistAssignmentExportPagedDataSource(pricelistAssignmentExportDataQuery, _pricelistAssignmentSearchService, _pricelistAssignmentService, _pricelistService, _catalogService); } return result ?? throw new ArgumentException($"Unsupported export query type: {dataQuery.GetType().Name}"); diff --git a/src/VirtoCommerce.PricingModule.Data/Handlers/DeletePricesProductChangedEventHandler.cs b/src/VirtoCommerce.PricingModule.Data/Handlers/DeletePricesProductChangedEventHandler.cs index a6bcafd9..9521ad6c 100644 --- a/src/VirtoCommerce.PricingModule.Data/Handlers/DeletePricesProductChangedEventHandler.cs +++ b/src/VirtoCommerce.PricingModule.Data/Handlers/DeletePricesProductChangedEventHandler.cs @@ -13,13 +13,13 @@ public class DeletePricesProductChangedEventHandler : IEventHandler p.Id).ToArray()); + await _priceService.DeleteAsync(searchResult.Results.Select(p => p.Id).ToArray()); } } while (searchResult.TotalCount > 0); diff --git a/src/VirtoCommerce.PricingModule.Data/Handlers/IndexPricesProductChangedEventHandler.cs b/src/VirtoCommerce.PricingModule.Data/Handlers/IndexPricesProductChangedEventHandler.cs index 8cf2aa2f..d30da22b 100644 --- a/src/VirtoCommerce.PricingModule.Data/Handlers/IndexPricesProductChangedEventHandler.cs +++ b/src/VirtoCommerce.PricingModule.Data/Handlers/IndexPricesProductChangedEventHandler.cs @@ -6,28 +6,34 @@ using VirtoCommerce.Platform.Core.Events; using VirtoCommerce.Platform.Core.Jobs; using VirtoCommerce.Platform.Core.Settings; +using VirtoCommerce.PricingModule.Core; using VirtoCommerce.PricingModule.Core.Events; using VirtoCommerce.PricingModule.Data.Search; +using VirtoCommerce.SearchModule.Core.BackgroundJobs; +using VirtoCommerce.SearchModule.Core.Extensions; using VirtoCommerce.SearchModule.Core.Model; -using VirtoCommerce.SearchModule.Data.BackgroundJobs; -using VirtoCommerce.SearchModule.Data.Services; namespace VirtoCommerce.PricingModule.Data.Handlers { public class IndexPricesProductChangedEventHandler : IEventHandler { private readonly ISettingsManager _settingsManager; + private readonly IIndexingJobService _indexingJobService; private readonly IEnumerable _configurations; - public IndexPricesProductChangedEventHandler(ISettingsManager settingsManager, IEnumerable configurations) + public IndexPricesProductChangedEventHandler( + ISettingsManager settingsManager, + IIndexingJobService indexingJobService, + IEnumerable configurations) { _settingsManager = settingsManager; + _indexingJobService = indexingJobService; _configurations = configurations; } - public Task Handle(PriceChangedEvent message) + public async Task Handle(PriceChangedEvent message) { - if (_settingsManager.GetValue(Core.ModuleConstants.Settings.General.EventBasedIndexation.Name, false)) + if (await _settingsManager.GetValueAsync(ModuleConstants.Settings.General.EventBasedIndexation)) { if (message == null) { @@ -38,11 +44,9 @@ public Task Handle(PriceChangedEvent message) .Select(x => new IndexEntry { Id = x.OldEntry.ProductId, EntryState = EntryState.Modified, Type = KnownDocumentTypes.Product }) .ToArray(); - IndexingJobs.EnqueueIndexAndDeleteDocuments(indexEntries, - JobPriority.Normal, _configurations.GetBuildersForProvider(typeof(ProductPriceDocumentChangesProvider)).ToList()); + _indexingJobService.EnqueueIndexAndDeleteDocuments(indexEntries, JobPriority.Normal, + _configurations.GetDocumentBuilders(KnownDocumentTypes.Product, typeof(ProductPriceDocumentChangesProvider)).ToList()); } - - return Task.CompletedTask; } } } diff --git a/src/VirtoCommerce.PricingModule.Data/Handlers/LogChangesChangedEventHandler.cs b/src/VirtoCommerce.PricingModule.Data/Handlers/LogChangesChangedEventHandler.cs index 3c00ffe9..57275743 100644 --- a/src/VirtoCommerce.PricingModule.Data/Handlers/LogChangesChangedEventHandler.cs +++ b/src/VirtoCommerce.PricingModule.Data/Handlers/LogChangesChangedEventHandler.cs @@ -30,7 +30,7 @@ public virtual Task Handle(PriceChangedEvent message) protected virtual async Task InnerHandle(GenericChangedEntryEvent @event) where T : IEntity { - var logPricingChangesEnabled = await _settingsManager.GetValueAsync(ModuleConstants.Settings.General.LogPricingChanges.Name, (bool)ModuleConstants.Settings.General.LogPricingChanges.DefaultValue); + var logPricingChangesEnabled = await _settingsManager.GetValueAsync(ModuleConstants.Settings.General.LogPricingChanges); if (logPricingChangesEnabled) { diff --git a/src/VirtoCommerce.PricingModule.Data/Repositories/IPricingRepository.cs b/src/VirtoCommerce.PricingModule.Data/Repositories/IPricingRepository.cs index 3ab16e5c..6dc6ec30 100644 --- a/src/VirtoCommerce.PricingModule.Data/Repositories/IPricingRepository.cs +++ b/src/VirtoCommerce.PricingModule.Data/Repositories/IPricingRepository.cs @@ -13,13 +13,13 @@ public interface IPricingRepository : IRepository IQueryable Prices { get; } IQueryable PricelistAssignments { get; } - Task> GetPricesByIdsAsync(IEnumerable priceIds); - Task> GetPricelistByIdsAsync(IEnumerable pricelistIds, string responseGroup); - Task> GetPricelistAssignmentsByIdAsync(IEnumerable assignmentsId); + Task> GetPricesByIdsAsync(IList priceIds); + Task> GetPricelistByIdsAsync(IList pricelistIds, string responseGroup); + Task> GetPricelistAssignmentsByIdAsync(IList assignmentsId); - Task DeletePricesAsync(IEnumerable ids); - Task DeletePricelistsAsync(IEnumerable ids); - Task DeletePricelistAssignmentsAsync(IEnumerable ids); + Task DeletePricesAsync(IList ids); + Task DeletePricelistsAsync(IList ids); + Task DeletePricelistAssignmentsAsync(IList ids); IQueryable GetMergedPrices(string basePriceListId, string priorityPriceListId); } diff --git a/src/VirtoCommerce.PricingModule.Data/Repositories/PricingRepositoryImpl.cs b/src/VirtoCommerce.PricingModule.Data/Repositories/PricingRepositoryImpl.cs index b61180f5..7a06b7a5 100644 --- a/src/VirtoCommerce.PricingModule.Data/Repositories/PricingRepositoryImpl.cs +++ b/src/VirtoCommerce.PricingModule.Data/Repositories/PricingRepositoryImpl.cs @@ -21,13 +21,13 @@ public PricingRepositoryImpl(PricingDbContext dbContext, IUnitOfWork unitOfWork public IQueryable Prices => DbContext.Set(); public IQueryable PricelistAssignments => DbContext.Set(); - public virtual async Task> GetPricesByIdsAsync(IEnumerable priceIds) + public virtual async Task> GetPricesByIdsAsync(IList priceIds) { var result = await Prices.Include(x => x.Pricelist).Where(x => priceIds.Contains(x.Id)).ToListAsync(); return result; } - public virtual async Task> GetPricelistByIdsAsync(IEnumerable pricelistIds, string responseGroup) + public virtual async Task> GetPricelistByIdsAsync(IList pricelistIds, string responseGroup) { var pricelistResponseGroup = EnumUtility.SafeParseFlags(responseGroup, PriceListResponseGroup.Full); @@ -42,23 +42,23 @@ public virtual async Task> GetPricelistByIdsAsync(I return result; } - public virtual async Task> GetPricelistAssignmentsByIdAsync(IEnumerable assignmentsId) + public virtual async Task> GetPricelistAssignmentsByIdAsync(IList assignmentsId) { var result = await PricelistAssignments.Include(x => x.Pricelist).Where(x => assignmentsId.Contains(x.Id)).ToListAsync(); return result; } - public Task DeletePricesAsync(IEnumerable ids) + public Task DeletePricesAsync(IList ids) { return ExecuteSqlCommandAsync("DELETE FROM \"Price\" WHERE Id IN ({0})", ids); } - public Task DeletePricelistsAsync(IEnumerable ids) + public Task DeletePricelistsAsync(IList ids) { return ExecuteSqlCommandAsync("DELETE FROM \"Pricelist\" WHERE Id IN ({0})", ids); } - public Task DeletePricelistAssignmentsAsync(IEnumerable ids) + public Task DeletePricelistAssignmentsAsync(IList ids) { return ExecuteSqlCommandAsync("DELETE FROM \"PricelistAssignment\" WHERE Id IN ({0})", ids); } @@ -116,9 +116,9 @@ private static Command GetSearchMergedPricesCommand(string basePriceListId, stri #endregion #region Commands - protected virtual Task ExecuteSqlCommandAsync(string commandTemplate, IEnumerable parameterValues) + protected virtual Task ExecuteSqlCommandAsync(string commandTemplate, IList parameterValues) { - if (parameterValues?.Count() > 0) + if (parameterValues?.Count > 0) { var command = CreateCommand(commandTemplate, parameterValues); return DbContext.Database.ExecuteSqlRawAsync(command.Text, command.Parameters); @@ -126,15 +126,15 @@ protected virtual Task ExecuteSqlCommandAsync(string commandTemplate, IEnumerabl return Task.CompletedTask; } - protected virtual Command CreateCommand(string commandTemplate, IEnumerable parameterValues) + protected virtual Command CreateCommand(string commandTemplate, IList parameterValues) { - var parameters = parameterValues.Select((v, i) => $"{{{i}}}"); + var parameters = parameterValues.Select((v, i) => $"{{{i}}}").ToList(); var parameterNames = string.Join(",", parameters); return new Command { Text = string.Format(commandTemplate, parameterNames), - Parameters = parameters.OfType(), + Parameters = parameters, }; } diff --git a/src/VirtoCommerce.PricingModule.Data/Search/ProductPriceDocumentBuilder.cs b/src/VirtoCommerce.PricingModule.Data/Search/ProductPriceDocumentBuilder.cs index 1340ab97..81193790 100644 --- a/src/VirtoCommerce.PricingModule.Data/Search/ProductPriceDocumentBuilder.cs +++ b/src/VirtoCommerce.PricingModule.Data/Search/ProductPriceDocumentBuilder.cs @@ -6,11 +6,11 @@ using VirtoCommerce.CatalogModule.Core.Model.Search; using VirtoCommerce.CatalogModule.Core.Search; using VirtoCommerce.Platform.Core.Common; -using VirtoCommerce.Platform.Core.GenericCrud; using VirtoCommerce.Platform.Core.Settings; using VirtoCommerce.PricingModule.Core; using VirtoCommerce.PricingModule.Core.Model; using VirtoCommerce.PricingModule.Core.Services; +using VirtoCommerce.SearchModule.Core.Extensions; using VirtoCommerce.SearchModule.Core.Model; using VirtoCommerce.SearchModule.Core.Services; @@ -35,7 +35,7 @@ public virtual async Task> GetDocumentsAsync(IList { var prices = await GetProductPrices(documentIds); - var useMaxIndexationPrice = UseMaxIndexationPrice(); + var useMaxIndexationPrice = await UseMaxIndexationPrice(); IList result = prices .GroupBy(p => p.ProductId) @@ -55,16 +55,16 @@ protected virtual IndexDocument CreateDocument(string productId, IList pr { foreach (var price in prices) { - document.Add(new IndexDocumentField($"price_{price.Currency}_{price.PricelistId}".ToLowerInvariant(), price.EffectiveValue) { IsRetrievable = true, IsFilterable = true }); + document.AddFilterableDecimal($"price_{price.Currency}_{price.PricelistId}".ToLowerInvariant(), price.EffectiveValue); } IndexPrice(document, prices, useMaxIndexationPrice); IndexPriceByCurrency(document, prices, useMaxIndexationPrice); - document.Add(new IndexDocumentField("is", prices.Any(x => x.Sale > 0) ? "sale" : "nosale") { IsRetrievable = true, IsFilterable = true, IsCollection = true }); + document.AddFilterableCollection("is", prices.Any(x => x.Sale > 0) ? "sale" : "nosale"); } - document.Add(new IndexDocumentField("is", prices?.Count > 0 ? "priced" : "unpriced") { IsRetrievable = true, IsFilterable = true, IsCollection = true }); + document.AddFilterableCollection("is", prices?.Count > 0 ? "priced" : "unpriced"); return document; } @@ -85,7 +85,7 @@ protected virtual void IndexPrice(IndexDocument document, IList prices, b var price = useMaxIndexationPrice ? prices.Max(x => x.EffectiveValue) : prices.Min(x => x.EffectiveValue); - document.Add(new IndexDocumentField("price", price) { IsRetrievable = true, IsFilterable = true, IsCollection = true }); + document.Add(new IndexDocumentField("price", price, IndexDocumentFieldValueType.Decimal) { IsRetrievable = true, IsFilterable = true, IsCollection = true }); } protected virtual void IndexPriceByCurrency(IndexDocument document, IList prices, bool useMaxIndexationPrice) @@ -95,13 +95,13 @@ protected virtual void IndexPriceByCurrency(IndexDocument document, IList var currencyPrice = useMaxIndexationPrice ? group.Max(x => x.EffectiveValue) : group.Min(x => x.EffectiveValue); - document.Add(new IndexDocumentField($"price_{group.Key}".ToLowerInvariant(), currencyPrice) { IsRetrievable = true, IsFilterable = true, IsCollection = true }); + document.Add(new IndexDocumentField($"price_{group.Key}".ToLowerInvariant(), currencyPrice, IndexDocumentFieldValueType.Decimal) { IsRetrievable = true, IsFilterable = true, IsCollection = true }); } } - private bool UseMaxIndexationPrice() + private async Task UseMaxIndexationPrice() { - var value = _settingsManager.GetValue(ModuleConstants.Settings.General.PriceIndexingValue.Name, ModuleConstants.Settings.General.PriceIndexingValue.DefaultValue as string); + var value = await _settingsManager.GetValueAsync(ModuleConstants.Settings.General.PriceIndexingValue); return value.EqualsInvariant(ModuleConstants.Settings.General.PriceIndexingValueMax); } @@ -167,7 +167,7 @@ private static void AddMinPrice(IndexDocument document, IList prices) }) .ToList(); - document.Add(new IndexDocumentField("__minVariationPrice", minPricesByCurrency) { ValueType = IndexDocumentFieldValueType.Complex, IsRetrievable = false, IsFilterable = false, IsCollection = false }); + document.Add(new IndexDocumentField("__minVariationPrice", minPricesByCurrency, IndexDocumentFieldValueType.Complex) { IsRetrievable = false, IsFilterable = false, IsCollection = false }); } } } diff --git a/src/VirtoCommerce.PricingModule.Data/Search/ProductPriceDocumentChangesProvider.cs b/src/VirtoCommerce.PricingModule.Data/Search/ProductPriceDocumentChangesProvider.cs index 26caa183..52acd4c6 100644 --- a/src/VirtoCommerce.PricingModule.Data/Search/ProductPriceDocumentChangesProvider.cs +++ b/src/VirtoCommerce.PricingModule.Data/Search/ProductPriceDocumentChangesProvider.cs @@ -107,7 +107,7 @@ protected virtual async Task> InnerGetC } //Re-index calendar prices only once per defined time interval - var lastIndexDate = _settingsManager.GetValue(ModuleConstants.Settings.General.IndexationDatePricingCalendar.Name, (DateTime?)null) ?? DateTime.MinValue; + var lastIndexDate = await _settingsManager.GetValueAsync(ModuleConstants.Settings.General.IndexationDatePricingCalendar); if ((DateTime.UtcNow - lastIndexDate) > _calendarChangesInterval && startDate != null && endDate != null) { workSkip = skip - workSkip; @@ -117,7 +117,7 @@ protected virtual async Task> InnerGetC result.TotalCount += calendarChanges.TotalCount; if (workTake > 0) { - _settingsManager.SetValue(ModuleConstants.Settings.General.IndexationDatePricingCalendar.Name, DateTime.UtcNow); + await _settingsManager.SetValueAsync(ModuleConstants.Settings.General.IndexationDatePricingCalendar.Name, DateTime.UtcNow); result.Results.AddRange(calendarChanges.Results); } } @@ -140,7 +140,7 @@ protected virtual async Task InnerGetTotalCountAsync(DateTime? startDate, D var result = await _changeLogSearchService.SearchAsync(criteria); //Re-index calendar prices only once per defined time interval - var lastIndexDate = _settingsManager.GetValue(ModuleConstants.Settings.General.IndexationDatePricingCalendar.Name, (DateTime?)null) ?? DateTime.MinValue; + var lastIndexDate = await _settingsManager.GetValueAsync(ModuleConstants.Settings.General.IndexationDatePricingCalendar); if ((DateTime.UtcNow - lastIndexDate) > _calendarChangesInterval && startDate != null && endDate != null) { var calendarChanges = await GetCalendarChangesAsync(startDate.Value, endDate.Value, 0, 0); @@ -172,11 +172,11 @@ protected virtual async Task> GetProductIdsForChangedPricesA }; // Get changes from operation log - var operations = (await _changeLogSearchService.SearchAsync(criteria)).Results.Select(x => x.ObjectId); + var operations = (await _changeLogSearchService.SearchAsync(criteria)).Results.Select(x => x.ObjectId).ToList(); using (var repository = _repositoryFactory()) { - var totalCount = operations.Count(); + var totalCount = operations.Count; for (var i = 0; i < totalCount; i += _batchSize) { diff --git a/src/VirtoCommerce.PricingModule.Data/Services/Search/MergedPriceSearchService.cs b/src/VirtoCommerce.PricingModule.Data/Services/MergedPriceSearchService.cs similarity index 92% rename from src/VirtoCommerce.PricingModule.Data/Services/Search/MergedPriceSearchService.cs rename to src/VirtoCommerce.PricingModule.Data/Services/MergedPriceSearchService.cs index fa1c3518..35d8df1f 100644 --- a/src/VirtoCommerce.PricingModule.Data/Services/Search/MergedPriceSearchService.cs +++ b/src/VirtoCommerce.PricingModule.Data/Services/MergedPriceSearchService.cs @@ -10,7 +10,6 @@ using VirtoCommerce.Platform.Caching; using VirtoCommerce.Platform.Core.Caching; using VirtoCommerce.Platform.Core.Common; -using VirtoCommerce.Platform.Core.GenericCrud; using VirtoCommerce.Platform.Data.Infrastructure; using VirtoCommerce.PricingModule.Core.Model; using VirtoCommerce.PricingModule.Core.Model.Search; @@ -18,18 +17,19 @@ using VirtoCommerce.PricingModule.Data.Model; using VirtoCommerce.PricingModule.Data.Repositories; -namespace VirtoCommerce.PricingModule.Data.Services.Search +namespace VirtoCommerce.PricingModule.Data.Services { public class MergedPriceSearchService : IMergedPriceSearchService { private readonly Func _repositoryFactory; - private readonly ICrudService _pricelistService; + private readonly IPricelistService _pricelistService; private readonly IItemService _itemService; private readonly IProductIndexedSearchService _productIndexedSearchService; private readonly IPlatformMemoryCache _platformMemoryCache; - public MergedPriceSearchService(Func repositoryFactory, - ICrudService pricelistService, + public MergedPriceSearchService( + Func repositoryFactory, + IPricelistService pricelistService, IItemService itemService, IProductIndexedSearchService productIndexedSearchService, IPlatformMemoryCache platformMemoryCache) @@ -87,7 +87,8 @@ public async Task SearchGroupsAsync(MergedPriceSea if (result.Results.Any()) { - var products = await _itemService.GetByIdsAsync(result.Results.Select(x => x.ProductId).ToArray(), ItemResponseGroup.ItemInfo.ToString()); + var productIds = result.Results.Select(x => x.ProductId).ToList(); + var products = await _itemService.GetNoCloneAsync(productIds, ItemResponseGroup.ItemInfo.ToString()); foreach (var group in result.Results) { var product = products.FirstOrDefault(x => x.Id == group.ProductId); @@ -146,7 +147,7 @@ public async Task SearchGroupPricesAsync(MergedPriceSea if (result.Results.Any()) { // get currency from base pricelist - var priceList = await _pricelistService.GetByIdAsync(criteria.BasePriceListId, PriceListResponseGroup.NoDetails.ToString()); + var priceList = await _pricelistService.GetNoCloneAsync(criteria.BasePriceListId, PriceListResponseGroup.NoDetails.ToString()); if (priceList != null) { foreach (var price in result.Results) diff --git a/src/VirtoCommerce.PricingModule.Data/Services/Search/PriceSearchService.cs b/src/VirtoCommerce.PricingModule.Data/Services/PriceSearchService.cs similarity index 80% rename from src/VirtoCommerce.PricingModule.Data/Services/Search/PriceSearchService.cs rename to src/VirtoCommerce.PricingModule.Data/Services/PriceSearchService.cs index d53ce374..2b6d5beb 100644 --- a/src/VirtoCommerce.PricingModule.Data/Services/Search/PriceSearchService.cs +++ b/src/VirtoCommerce.PricingModule.Data/Services/PriceSearchService.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Options; using VirtoCommerce.CatalogModule.Core.Model; using VirtoCommerce.CatalogModule.Core.Model.Search; using VirtoCommerce.CatalogModule.Core.Search; @@ -15,30 +16,41 @@ using VirtoCommerce.Platform.Data.Infrastructure; using VirtoCommerce.PricingModule.Core.Model; using VirtoCommerce.PricingModule.Core.Model.Search; +using VirtoCommerce.PricingModule.Core.Services; using VirtoCommerce.PricingModule.Data.Model; using VirtoCommerce.PricingModule.Data.Repositories; namespace VirtoCommerce.PricingModule.Data.Services { - public class PriceSearchService : SearchService + public class PriceSearchService : SearchService, IPriceSearchService { /// /// Limits counts of products that can be found by keyword for price search /// - const int maxSearchProductByKeywordResults = 1000; + private const int _maxSearchProductByKeywordResults = 1000; + private readonly Func _repositoryFactory; + private readonly IPlatformMemoryCache _platformMemoryCache; + private readonly IPriceService _crudService; private readonly IProductIndexedSearchService _productIndexedSearchService; - private readonly Dictionary _pricesSortingAliases = new Dictionary(); - - public PriceSearchService(Func repositoryFactory, IPlatformMemoryCache platformMemoryCache, - ICrudService priceService, IProductIndexedSearchService productIndexedSearchService) - : base(repositoryFactory, platformMemoryCache, priceService) + private readonly Dictionary _pricesSortingAliases = new(); + + public PriceSearchService( + Func repositoryFactory, + IPlatformMemoryCache platformMemoryCache, + IPriceService crudService, + IOptions crudOptions, + IProductIndexedSearchService productIndexedSearchService) + : base(repositoryFactory, platformMemoryCache, crudService, crudOptions) { _pricesSortingAliases["prices"] = ReflectionUtility.GetPropertyName(x => x.List); + _repositoryFactory = repositoryFactory; + _platformMemoryCache = platformMemoryCache; + _crudService = crudService; _productIndexedSearchService = productIndexedSearchService; } - public override Task SearchAsync(PricesSearchCriteria criteria) + public override Task SearchAsync(PricesSearchCriteria criteria, bool clone = true) { var cacheKey = CacheKey.With(GetType(), nameof(SearchAsync), criteria.GetCacheKey()); return _platformMemoryCache.GetOrCreateExclusiveAsync(cacheKey, async cacheEntry => @@ -59,14 +71,17 @@ public override Task SearchAsync(PricesSearchCriteria criteri if (criteria.GroupByProducts) { // unique priced product IDs - var pricedProductsQuery = query.Select(x => x.ProductId).OrderBy(x => x).Distinct(); + var pricedProductsQuery = query.Select(x => x.ProductId).Distinct(); result.TotalCount = await pricedProductsQuery.CountAsync(); if (criteria.Take > 0) { - query = query.Where(x => pricedProductsQuery - .OrderBy(x => x) - .Skip(criteria.Skip).Take(criteria.Take).Contains(x.ProductId)); + query = query + .Where(x => pricedProductsQuery + .OrderBy(y => y) + .Skip(criteria.Skip) + .Take(criteria.Take) + .Contains(x.ProductId)); } } else @@ -83,7 +98,7 @@ public override Task SearchAsync(PricesSearchCriteria criteri .AsNoTracking() .ToListAsync(); - var unorderedResults = await _crudService.GetByIdsAsync(priceIds); + var unorderedResults = await _crudService.GetAsync(priceIds, responseGroup: null, clone); result.Results = unorderedResults.OrderBy(x => priceIds.IndexOf(x.Id)).ToList(); } } @@ -136,7 +151,7 @@ private async Task> BuildQueryAsync(IRepository reposito var searchCriteria = AbstractTypeFactory.TryCreateInstance(); searchCriteria.Keyword = criteria.Keyword; searchCriteria.Skip = 0; - searchCriteria.Take = maxSearchProductByKeywordResults; + searchCriteria.Take = _maxSearchProductByKeywordResults; searchCriteria.Sort = criteria.Sort.Replace("product.", string.Empty); searchCriteria.ResponseGroup = ItemResponseGroup.ItemInfo.ToString(); searchCriteria.WithHidden = true; diff --git a/src/VirtoCommerce.PricingModule.Data/Services/Crud/PriceService.cs b/src/VirtoCommerce.PricingModule.Data/Services/PriceService.cs similarity index 76% rename from src/VirtoCommerce.PricingModule.Data/Services/Crud/PriceService.cs rename to src/VirtoCommerce.PricingModule.Data/Services/PriceService.cs index 422d316a..2499bbc6 100644 --- a/src/VirtoCommerce.PricingModule.Data/Services/Crud/PriceService.cs +++ b/src/VirtoCommerce.PricingModule.Data/Services/PriceService.cs @@ -6,26 +6,35 @@ using VirtoCommerce.Platform.Core.Caching; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.Events; -using VirtoCommerce.Platform.Core.GenericCrud; using VirtoCommerce.Platform.Data.GenericCrud; using VirtoCommerce.PricingModule.Core.Events; using VirtoCommerce.PricingModule.Core.Model; +using VirtoCommerce.PricingModule.Core.Services; using VirtoCommerce.PricingModule.Data.Model; using VirtoCommerce.PricingModule.Data.Repositories; namespace VirtoCommerce.PricingModule.Data.Services { - public class PriceService : CrudService + public class PriceService : CrudService, IPriceService { - private readonly ICrudService _pricelistService; - public PriceService(Func repositoryFactory, IPlatformMemoryCache platformMemoryCache, IEventPublisher eventPublisher, ICrudService pricelistService) + private readonly Func _repositoryFactory; + private readonly IEventPublisher _eventPublisher; + private readonly IPricelistService _pricelistService; + + public PriceService( + Func repositoryFactory, + IPlatformMemoryCache platformMemoryCache, + IEventPublisher eventPublisher, + IPricelistService pricelistService) : base(repositoryFactory, platformMemoryCache, eventPublisher) { + _repositoryFactory = repositoryFactory; + _eventPublisher = eventPublisher; _pricelistService = pricelistService; } - public override async Task SaveChangesAsync(IEnumerable models) + public override async Task SaveChangesAsync(IList models) { var pkMap = new PrimaryKeyResolvingMap(); var changedEntries = new List>(); @@ -37,9 +46,9 @@ public override async Task SaveChangesAsync(IEnumerable models) foreach (var priceWithoutPricelistGroup in models.Where(x => x.PricelistId == null).GroupBy(x => x.Currency)) { var defaultPriceListId = GetDefaultPriceListName(priceWithoutPricelistGroup.Key); - var pricelists = await _pricelistService.GetByIdsAsync(new[] { defaultPriceListId }); - if (pricelists.IsNullOrEmpty()) - { + var pricelist = await _pricelistService.GetNoCloneAsync(defaultPriceListId); + if (pricelist == null) + { repository.Add(AbstractTypeFactory.TryCreateInstance().FromModel(GetDefaultPriceList(priceWithoutPricelistGroup, defaultPriceListId), pkMap)); } foreach (var priceWithoutPricelist in priceWithoutPricelistGroup) @@ -75,12 +84,12 @@ public override async Task SaveChangesAsync(IEnumerable models) } } - protected override async Task> LoadEntities(IRepository repository, IEnumerable ids, string responseGroup) + protected override Task> LoadEntities(IRepository repository, IList ids, string responseGroup) { - return await ((IPricingRepository)repository).GetPricesByIdsAsync(ids); + return ((IPricingRepository)repository).GetPricesByIdsAsync(ids); } - protected override void ClearCache(IEnumerable models) + protected override void ClearCache(IList models) { GenericCachingRegion.ExpireRegion(); base.ClearCache(models); @@ -95,7 +104,8 @@ protected virtual Pricelist GetDefaultPriceList(IGrouping priceWi defaultPriceList.Description = defaultPriceListId; return defaultPriceList; } - private string GetDefaultPriceListName(string currency) + + private static string GetDefaultPriceListName(string currency) { var result = "Default" + currency; return result; diff --git a/src/VirtoCommerce.PricingModule.Data/Services/Search/PricelistAssignmentSearchService.cs b/src/VirtoCommerce.PricingModule.Data/Services/PricelistAssignmentSearchService.cs similarity index 80% rename from src/VirtoCommerce.PricingModule.Data/Services/Search/PricelistAssignmentSearchService.cs rename to src/VirtoCommerce.PricingModule.Data/Services/PricelistAssignmentSearchService.cs index f220f6ac..3584ddd4 100644 --- a/src/VirtoCommerce.PricingModule.Data/Services/Search/PricelistAssignmentSearchService.cs +++ b/src/VirtoCommerce.PricingModule.Data/Services/PricelistAssignmentSearchService.cs @@ -1,23 +1,27 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Options; using VirtoCommerce.Platform.Core.Caching; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.GenericCrud; using VirtoCommerce.Platform.Data.GenericCrud; using VirtoCommerce.PricingModule.Core.Model; using VirtoCommerce.PricingModule.Core.Model.Search; +using VirtoCommerce.PricingModule.Core.Services; using VirtoCommerce.PricingModule.Data.Model; using VirtoCommerce.PricingModule.Data.Repositories; namespace VirtoCommerce.PricingModule.Data.Services { - public class PricelistAssignmentSearchService : SearchService + public class PricelistAssignmentSearchService : SearchService, IPricelistAssignmentSearchService { - - public PricelistAssignmentSearchService(Func repositoryFactory, IPlatformMemoryCache platformMemoryCache, - ICrudService pricelistAssignmentService) - : base(repositoryFactory, platformMemoryCache, pricelistAssignmentService) + public PricelistAssignmentSearchService( + Func repositoryFactory, + IPlatformMemoryCache platformMemoryCache, + IPricelistAssignmentService crudService, + IOptions crudOptions) + : base(repositoryFactory, platformMemoryCache, crudService, crudOptions) { } diff --git a/src/VirtoCommerce.PricingModule.Data/Services/Crud/PricelistAssignmentService.cs b/src/VirtoCommerce.PricingModule.Data/Services/PricelistAssignmentService.cs similarity index 72% rename from src/VirtoCommerce.PricingModule.Data/Services/Crud/PricelistAssignmentService.cs rename to src/VirtoCommerce.PricingModule.Data/Services/PricelistAssignmentService.cs index 66d7ee79..597d8e4f 100644 --- a/src/VirtoCommerce.PricingModule.Data/Services/Crud/PricelistAssignmentService.cs +++ b/src/VirtoCommerce.PricingModule.Data/Services/PricelistAssignmentService.cs @@ -9,16 +9,18 @@ using VirtoCommerce.Platform.Data.GenericCrud; using VirtoCommerce.PricingModule.Core.Events; using VirtoCommerce.PricingModule.Core.Model; +using VirtoCommerce.PricingModule.Core.Services; using VirtoCommerce.PricingModule.Data.Model; using VirtoCommerce.PricingModule.Data.Repositories; namespace VirtoCommerce.PricingModule.Data.Services { - public class PricelistAssignmentService : CrudService + public class PricelistAssignmentService : CrudService, IPricelistAssignmentService { private readonly AbstractValidator> _validator; - public PricelistAssignmentService(Func repositoryFactory, + public PricelistAssignmentService( + Func repositoryFactory, IPlatformMemoryCache platformMemoryCache, IEventPublisher eventPublisher, AbstractValidator> validator) @@ -27,19 +29,19 @@ public PricelistAssignmentService(Func repositoryFactory, _validator = validator; } - protected override async Task> LoadEntities(IRepository repository, IEnumerable ids, string responseGroup) + protected override Task> LoadEntities(IRepository repository, IList ids, string responseGroup) { - return await ((IPricingRepository)repository).GetPricelistAssignmentsByIdAsync(ids); + return ((IPricingRepository)repository).GetPricelistAssignmentsByIdAsync(ids); } - protected override Task BeforeSaveChanges(IEnumerable models) + protected override Task BeforeSaveChanges(IList models) { _validator.ValidateAndThrow(models); return base.BeforeSaveChanges(models); } - protected override void ClearCache(IEnumerable models) + protected override void ClearCache(IList models) { foreach (var assignment in models) { diff --git a/src/VirtoCommerce.PricingModule.Data/Services/Search/PricelistSearchService.cs b/src/VirtoCommerce.PricingModule.Data/Services/PricelistSearchService.cs similarity index 81% rename from src/VirtoCommerce.PricingModule.Data/Services/Search/PricelistSearchService.cs rename to src/VirtoCommerce.PricingModule.Data/Services/PricelistSearchService.cs index bef56a73..5c47b628 100644 --- a/src/VirtoCommerce.PricingModule.Data/Services/Search/PricelistSearchService.cs +++ b/src/VirtoCommerce.PricingModule.Data/Services/PricelistSearchService.cs @@ -1,23 +1,27 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Options; using VirtoCommerce.Platform.Core.Caching; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.GenericCrud; using VirtoCommerce.Platform.Data.GenericCrud; using VirtoCommerce.PricingModule.Core.Model; using VirtoCommerce.PricingModule.Core.Model.Search; +using VirtoCommerce.PricingModule.Core.Services; using VirtoCommerce.PricingModule.Data.Model; using VirtoCommerce.PricingModule.Data.Repositories; namespace VirtoCommerce.PricingModule.Data.Services { - public class PricelistSearchService : SearchService + public class PricelistSearchService : SearchService, IPricelistSearchService { - - public PricelistSearchService(Func repositoryFactory, IPlatformMemoryCache platformMemoryCache, - ICrudService pricelistService) - : base(repositoryFactory, platformMemoryCache, pricelistService) + public PricelistSearchService( + Func repositoryFactory, + IPlatformMemoryCache platformMemoryCache, + IPricelistService crudService, + IOptions crudOptions) + : base(repositoryFactory, platformMemoryCache, crudService, crudOptions) { } diff --git a/src/VirtoCommerce.PricingModule.Data/Services/Crud/PricelistService.cs b/src/VirtoCommerce.PricingModule.Data/Services/PricelistService.cs similarity index 70% rename from src/VirtoCommerce.PricingModule.Data/Services/Crud/PricelistService.cs rename to src/VirtoCommerce.PricingModule.Data/Services/PricelistService.cs index 61605342..cd853c8f 100644 --- a/src/VirtoCommerce.PricingModule.Data/Services/Crud/PricelistService.cs +++ b/src/VirtoCommerce.PricingModule.Data/Services/PricelistService.cs @@ -7,22 +7,22 @@ using VirtoCommerce.Platform.Data.GenericCrud; using VirtoCommerce.PricingModule.Core.Events; using VirtoCommerce.PricingModule.Core.Model; +using VirtoCommerce.PricingModule.Core.Services; using VirtoCommerce.PricingModule.Data.Model; using VirtoCommerce.PricingModule.Data.Repositories; namespace VirtoCommerce.PricingModule.Data.Services { - public class PricelistService : CrudService + public class PricelistService : CrudService, IPricelistService { public PricelistService(Func repositoryFactory, IPlatformMemoryCache platformMemoryCache, IEventPublisher eventPublisher) : base(repositoryFactory, platformMemoryCache, eventPublisher) { } - protected override async Task> LoadEntities(IRepository repository, IEnumerable ids, string responseGroup) + protected override Task> LoadEntities(IRepository repository, IList ids, string responseGroup) { - return await ((IPricingRepository)repository).GetPricelistByIdsAsync(ids, responseGroup); + return ((IPricingRepository)repository).GetPricelistByIdsAsync(ids, responseGroup); } - } } diff --git a/src/VirtoCommerce.PricingModule.Data/Services/PricingEvaluatorService.cs b/src/VirtoCommerce.PricingModule.Data/Services/PricingEvaluatorService.cs index 86200af5..13852c64 100644 --- a/src/VirtoCommerce.PricingModule.Data/Services/PricingEvaluatorService.cs +++ b/src/VirtoCommerce.PricingModule.Data/Services/PricingEvaluatorService.cs @@ -16,8 +16,6 @@ using VirtoCommerce.PricingModule.Core.Services; using VirtoCommerce.PricingModule.Data.Repositories; -#pragma warning disable CS0618 // Allow to use obsoleted - namespace VirtoCommerce.PricingModule.Data.Services { public class PricingEvaluatorService : IPricingEvaluatorService @@ -43,13 +41,13 @@ IPricingPriorityFilterPolicy pricingPriorityFilterPolicy _productService = productService; } - public virtual async Task> EvaluatePriceListsAsync(PriceEvaluationContext evalContext) + public virtual async Task> EvaluatePriceListsAsync(PriceEvaluationContext evalContext) { List assignmentsToReturn; var query = await PriceListAssignmentAsync(evalContext); if (evalContext.SkipAssignmentValidation) { - // do NOT use ToListAsync as "query" is not EF IAsyncQuerable + // do NOT use ToListAsync as "query" is not EF IAsyncQueryable assignmentsToReturn = query.ToList(); } else @@ -80,7 +78,8 @@ public virtual async Task> EvaluatePriceListsAsync(PriceE { x.Pricelist.Priority = x.Priority; return x.Pricelist; - }); + }) + .ToList(); } public virtual async Task> PriceListAssignmentAsync(PriceEvaluationContext evalContext) @@ -95,12 +94,12 @@ public virtual async Task> PriceListAssignmentAs var query = priceListAssignments.AsQueryable(); - var predictate = GetEvaluationPredicate(evalContext); - query = query.Where(predictate); + var predicate = GetEvaluationPredicate(evalContext); + query = query.Where(predicate); if (evalContext.Currency != null) { - query = query.Where(x => x.Pricelist.Currency == evalContext.Currency.ToString()); + query = query.Where(x => x.Pricelist.Currency == evalContext.Currency); } if (evalContext.CertainDate != null) @@ -122,12 +121,12 @@ private Expression> GetEvaluationPredicate(Price if (evalContext.StoreId != null) { - predicate = PredicateBuilder.Or(predicate, x => x.StoreId == evalContext.StoreId); + predicate = predicate.Or(x => x.StoreId == evalContext.StoreId); } if (evalContext.CatalogId != null) { - predicate = PredicateBuilder.Or(predicate, x => x.CatalogId == evalContext.CatalogId); + predicate = predicate.Or(x => x.CatalogId == evalContext.CatalogId); } return predicate; @@ -144,7 +143,7 @@ public virtual async Task GetAllPricelistAssignments() } } - public virtual async Task> EvaluateProductPricesAsync(PriceEvaluationContext evalContext) + public virtual async Task> EvaluateProductPricesAsync(PriceEvaluationContext evalContext) { if (evalContext == null) { @@ -209,9 +208,9 @@ private async Task> PostProcessPrices(PriceEvaluationContext evalCon //Try to inherit prices for variations from their main product //Need find products without price it may be a variation without implicitly price defined and try to get price from main product - var variations = (await _productService.GetByIdsAsync(productIdsWithoutPrice, ItemResponseGroup.ItemInfo.ToString())) + var variations = (await _productService.GetNoCloneAsync(productIdsWithoutPrice, ItemResponseGroup.ItemInfo.ToString())) .Where(x => x.MainProductId != null).ToList(); - evalContext = evalContext.Clone() as PriceEvaluationContext; + evalContext = evalContext.CloneTyped(); evalContext.ProductIds = variations.Select(x => x.MainProductId).Distinct().ToArray(); if (evalContext.ProductIds.IsNullOrEmpty()) @@ -224,7 +223,7 @@ private async Task> PostProcessPrices(PriceEvaluationContext evalCon { foreach (var variation in variations.Where(x => x.MainProductId == inheritedPrice.ProductId)) { - var variationPrice = inheritedPrice.Clone() as Price; + var variationPrice = inheritedPrice.CloneTyped(); //Reset id for correct override price in possible update variationPrice.Id = null; variationPrice.ProductId = variation.Id; diff --git a/src/VirtoCommerce.PricingModule.Data/Services/PricingSearchServiceImpl.cs b/src/VirtoCommerce.PricingModule.Data/Services/PricingSearchServiceImpl.cs deleted file mode 100644 index 08191433..00000000 --- a/src/VirtoCommerce.PricingModule.Data/Services/PricingSearchServiceImpl.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Threading.Tasks; -using VirtoCommerce.Platform.Core.GenericCrud; -using VirtoCommerce.PricingModule.Core.Model; -using VirtoCommerce.PricingModule.Core.Model.Search; -using VirtoCommerce.PricingModule.Core.Services; - -namespace VirtoCommerce.PricingModule.Data.Services -{ - [Obsolete("Implementation was decoupled to separate implementations of ISearchService, " + - "ISearchService, " + - "ISearchService") ] - public class PricingSearchServiceImpl : IPricingSearchService - { - - private readonly ISearchService _pricelistAssignmentSearchService; - private readonly ISearchService _pricelistSearchService; - private readonly ISearchService _priceSearchService; - - public PricingSearchServiceImpl(ISearchService pricelistAssignmentSearchService, - ISearchService pricelistSearchService, - ISearchService priceSearchService) - { - _pricelistAssignmentSearchService = pricelistAssignmentSearchService; - _pricelistSearchService = pricelistSearchService; - _priceSearchService = priceSearchService; - } - - public Task SearchPricelistAssignmentsAsync(PricelistAssignmentsSearchCriteria criteria) - { - return _pricelistAssignmentSearchService.SearchAsync(criteria); - } - - public Task SearchPricelistsAsync(PricelistSearchCriteria criteria) - { - return _pricelistSearchService.SearchAsync(criteria); - } - - public Task SearchPricesAsync(PricesSearchCriteria criteria) - { - return _priceSearchService.SearchAsync(criteria); - } - } -} - diff --git a/src/VirtoCommerce.PricingModule.Data/Services/PricingServiceImpl.cs b/src/VirtoCommerce.PricingModule.Data/Services/PricingServiceImpl.cs deleted file mode 100644 index 8bbf1e1a..00000000 --- a/src/VirtoCommerce.PricingModule.Data/Services/PricingServiceImpl.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using VirtoCommerce.Platform.Core.GenericCrud; -using VirtoCommerce.PricingModule.Core.Model; -using VirtoCommerce.PricingModule.Core.Services; - -namespace VirtoCommerce.PricingModule.Data.Services -{ - [Obsolete("Implementation was decoupled to separate implementations of interfaces IPricingEvaluatorService, ICrudService, ICrudService, ICrudService")] - public class PricingServiceImpl : IPricingService - { - private readonly ICrudService _pricelistAssignmentService; - private readonly ICrudService _pricelistService; - private readonly ICrudService _priceService; - private readonly IPricingEvaluatorService _pricingEvaluatorService; - - - public PricingServiceImpl( - ICrudService pricelistAssignmentService, - ICrudService pricelistService, - ICrudService priceService, - IPricingEvaluatorService pricingEvaluatorService - ) - { - _pricelistAssignmentService = pricelistAssignmentService; - _pricelistService = pricelistService; - _priceService = priceService; - _pricingEvaluatorService = pricingEvaluatorService; - } - - public Task DeletePricelistsAssignmentsAsync(string[] ids) - { - return _pricelistAssignmentService.DeleteAsync(ids); - } - - public Task DeletePricelistsAsync(string[] ids) - { - return _pricelistService.DeleteAsync(ids); - } - - public Task DeletePricesAsync(string[] ids) - { - return _priceService.DeleteAsync(ids); - } - - public Task> EvaluatePriceListsAsync(PriceEvaluationContext evalContext) - { - return _pricingEvaluatorService.EvaluatePriceListsAsync(evalContext); - } - - public Task> EvaluateProductPricesAsync(PriceEvaluationContext evalContext) - { - return _pricingEvaluatorService.EvaluateProductPricesAsync(evalContext); - } - - public async Task GetPricelistAssignmentsByIdAsync(string[] ids) - { - return (await _pricelistAssignmentService.GetByIdsAsync(ids)).ToArray(); - } - - public async Task GetPricelistsByIdAsync(string[] ids, string responseGroup = null) - { - return (await _pricelistService.GetByIdsAsync(ids, responseGroup)).ToArray(); - } - - public async Task GetPricesByIdAsync(string[] ids) - { - return (await _priceService.GetByIdsAsync(ids)).ToArray(); - } - - public Task SavePricelistAssignmentsAsync(PricelistAssignment[] assignments) - { - return _pricelistAssignmentService.SaveChangesAsync(assignments); - } - - public Task SavePricelistsAsync(Pricelist[] priceLists) - { - return _pricelistService.SaveChangesAsync(priceLists); - } - - public Task SavePricesAsync(Price[] prices) - { - return _priceService.SaveChangesAsync(prices); - } - } -} diff --git a/src/VirtoCommerce.PricingModule.Data/VirtoCommerce.PricingModule.Data.csproj b/src/VirtoCommerce.PricingModule.Data/VirtoCommerce.PricingModule.Data.csproj index 64bcd4b4..97316dee 100644 --- a/src/VirtoCommerce.PricingModule.Data/VirtoCommerce.PricingModule.Data.csproj +++ b/src/VirtoCommerce.PricingModule.Data/VirtoCommerce.PricingModule.Data.csproj @@ -1,34 +1,26 @@ - - net6.0 - true - 1591 - True - true - true - true - snupkg - - - - false - - - - - - - - - - - - - - - - - - - + + net6.0 + true + 1591 + True + true + true + true + snupkg + + + + false + + + + + + + + + + + diff --git a/src/VirtoCommerce.PricingModule.Web/Controllers/Api/PricingModuleController.cs b/src/VirtoCommerce.PricingModule.Web/Controllers/Api/PricingModuleController.cs index b7f1cb6b..89edeff7 100644 --- a/src/VirtoCommerce.PricingModule.Web/Controllers/Api/PricingModuleController.cs +++ b/src/VirtoCommerce.PricingModule.Web/Controllers/Api/PricingModuleController.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -16,32 +15,45 @@ using VirtoCommerce.PricingModule.Core.Model.Search; using VirtoCommerce.PricingModule.Core.Services; -#pragma warning disable CS0618 // Allow to use obsoleted - namespace VirtoCommerce.PricingModule.Web.Controllers.Api { [Route("")] [Authorize(ModuleConstants.Security.Permissions.Read)] public class PricingModuleController : Controller { - private readonly IPricingService _pricingService; - private readonly IPricingSearchService _pricingSearchService; + private readonly IPriceSearchService _priceSearchService; + private readonly IPriceService _priceService; + private readonly IPricelistSearchService _pricelistSearchService; + private readonly IPricelistService _pricelistService; + private readonly IPricelistAssignmentSearchService _pricelistAssignmentSearchService; + private readonly IPricelistAssignmentService _pricelistAssignmentService; + private readonly IPricingEvaluatorService _pricingEvaluatorService; private readonly IItemService _itemService; private readonly IBlobUrlResolver _blobUrlResolver; private readonly AbstractValidator _priceListValidator; private readonly IMergedPriceSearchService _mergedPriceSearchService; public PricingModuleController( - IPricingService pricingService, + IPriceSearchService priceSearchService, + IPriceService priceService, + IPricelistSearchService pricelistSearchService, + IPricelistService pricelistService, + IPricelistAssignmentSearchService pricelistAssignmentSearchService, + IPricelistAssignmentService pricelistAssignmentService, + IPricingEvaluatorService pricingEvaluatorService, IItemService itemService, - IPricingSearchService pricingSearchService, IMergedPriceSearchService mergedPriceSearchService, IBlobUrlResolver blobUrlResolver, AbstractValidator priceListValidator) { - _pricingService = pricingService; + _priceSearchService = priceSearchService; + _priceService = priceService; + _pricelistSearchService = pricelistSearchService; + _pricelistService = pricelistService; + _pricelistAssignmentSearchService = pricelistAssignmentSearchService; + _pricelistAssignmentService = pricelistAssignmentService; + _pricingEvaluatorService = pricingEvaluatorService; _itemService = itemService; - _pricingSearchService = pricingSearchService; _blobUrlResolver = blobUrlResolver; _priceListValidator = priceListValidator; _mergedPriceSearchService = mergedPriceSearchService; @@ -54,9 +66,9 @@ public PricingModuleController( /// Prices array [HttpPost] [Route("api/pricing/evaluate")] - public async Task> EvaluatePrices([FromBody] PriceEvaluationContext evalContext) + public async Task>> EvaluatePrices([FromBody] PriceEvaluationContext evalContext) { - var result = (await _pricingService.EvaluateProductPricesAsync(evalContext)).ToArray(); + var result = await _pricingEvaluatorService.EvaluateProductPricesAsync(evalContext); return Ok(result); } @@ -69,9 +81,9 @@ public async Task> EvaluatePrices([FromBody] PriceEvaluati /// Pricelist array [HttpPost] [Route("api/pricing/pricelists/evaluate")] - public async Task> EvaluatePriceLists([FromBody] PriceEvaluationContext evalContext) + public async Task>> EvaluatePriceLists([FromBody] PriceEvaluationContext evalContext) { - var result = (await _pricingService.EvaluatePriceListsAsync(evalContext)).ToArray(); + var result = await _pricingEvaluatorService.EvaluatePriceListsAsync(evalContext); return Ok(result); } /// @@ -82,7 +94,7 @@ public async Task> EvaluatePriceLists([FromBody] Price [Route("api/pricing/assignments/{id}")] public async Task> GetPricelistAssignmentById(string id) { - var assignment = (await _pricingService.GetPricelistAssignmentsByIdAsync(new[] { id })).FirstOrDefault(); + var assignment = await _pricelistAssignmentService.GetByIdAsync(id); if (assignment != null) { assignment.DynamicExpression?.MergeFromPrototype(AbstractTypeFactory.TryCreateInstance()); @@ -118,7 +130,7 @@ public async Task> SearchPricelists(Pricelis { criteria = new PricelistSearchCriteria(); } - var result = await _pricingSearchService.SearchPricelistsAsync(criteria); + var result = await _pricelistSearchService.SearchNoCloneAsync(criteria); return Ok(result); } @@ -134,7 +146,7 @@ public async Task> SearchPricelist { criteria = new PricelistAssignmentsSearchCriteria(); } - var result = await _pricingSearchService.SearchPricelistAssignmentsAsync(criteria); + var result = await _pricelistAssignmentSearchService.SearchNoCloneAsync(criteria); return Ok(result); } @@ -168,11 +180,12 @@ private async Task InnerSearchProductPrices(PricesSear } var result = AbstractTypeFactory.TryCreateInstance(); - var searchResult = await _pricingSearchService.SearchPricesAsync(criteria); + var searchResult = await _priceSearchService.SearchNoCloneAsync(criteria); result.TotalCount = searchResult.TotalCount; result.Results = new List(); - var products = await _itemService.GetByIdsAsync(searchResult.Results.Select(x => x.ProductId).Distinct().ToArray(), ItemResponseGroup.ItemInfo.ToString()); + var productIds = searchResult.Results.Select(x => x.ProductId).Distinct().ToList(); + var products = await _itemService.GetNoCloneAsync(productIds, ItemResponseGroup.ItemInfo.ToString()); foreach (var productPricesGroup in searchResult.Results.GroupBy(x => x.ProductId)) { var productPrice = new ProductPrice @@ -207,12 +220,12 @@ private async Task InnerSearchProductPrices(PricesSear /// Product id [HttpGet] [Route("api/products/{productId}/prices")] - public async Task> EvaluateProductPrices(string productId) + public async Task>> EvaluateProductPrices(string productId) { var priceEvalContext = AbstractTypeFactory.TryCreateInstance(); priceEvalContext.ProductIds = new[] { productId }; - var product = (await _itemService.GetByIdsAsync(new[] { productId }, ItemResponseGroup.ItemInfo.ToString())).FirstOrDefault(); + var product = await _itemService.GetNoCloneAsync(productId, ItemResponseGroup.ItemInfo.ToString()); if (product != null) { priceEvalContext.CatalogId = product.CatalogId; @@ -228,7 +241,7 @@ public async Task> EvaluateProductPrices(string productId) /// Catalog id [HttpGet] [Route("api/products/{productId}/{catalogId}/pricesWidget")] - public Task> EvaluateProductPricesForCatalog(string productId, string catalogId) + public Task>> EvaluateProductPricesForCatalog(string productId, string catalogId) { var priceEvalContext = AbstractTypeFactory.TryCreateInstance(); priceEvalContext.ProductIds = new[] { productId }; @@ -246,7 +259,7 @@ public Task> EvaluateProductPricesForCatalog(string produc [Authorize(ModuleConstants.Security.Permissions.Create)] public async Task> CreatePricelistAssignment([FromBody] PricelistAssignment assignment) { - await _pricingService.SavePricelistAssignmentsAsync(new[] { assignment }); + await _pricelistAssignmentService.SaveChangesAsync(new[] { assignment }); return Ok(assignment); } @@ -261,7 +274,7 @@ public async Task> CreatePricelistAssignment([ [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)] public async Task UpdatePriceListAssignment([FromBody] PricelistAssignment assignment) { - await _pricingService.SavePricelistAssignmentsAsync(new[] { assignment }); + await _pricelistAssignmentService.SaveChangesAsync(new[] { assignment }); return NoContent(); } @@ -271,12 +284,12 @@ public async Task UpdatePriceListAssignment([FromBody] PricelistAs [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)] public async Task UpdateProductsPrices([FromBody] ProductPrice[] productPrices) { - var result = await _pricingSearchService.SearchPricesAsync(new PricesSearchCriteria + var result = await _priceSearchService.SearchAsync(new PricesSearchCriteria { + ProductIds = productPrices.Select(x => x.ProductId).ToList(), Take = int.MaxValue, - ProductIds = productPrices.Select(x => x.ProductId).ToArray() }); - var targetPricesGroups = result.Results.GroupBy(x => x.PricelistId); + var targetPricesGroups = result.Results.GroupBy(x => x.PricelistId).ToDictionary(g => g.Key); var sourcePricesGroups = productPrices.SelectMany(x => x.Prices).GroupBy(x => x.PricelistId); var changedPrices = new List(); @@ -284,8 +297,7 @@ public async Task UpdateProductsPrices([FromBody] ProductPrice[] p foreach (var sourcePricesGroup in sourcePricesGroups) { - var targetPricesGroup = targetPricesGroups.FirstOrDefault(x => x.Key == sourcePricesGroup.Key); - if (targetPricesGroup != null) + if (targetPricesGroups.TryGetValue(sourcePricesGroup.Key, out var targetPricesGroup)) { sourcePricesGroup.ToArray().CompareTo(targetPricesGroup.ToArray(), EqualityComparer.Default, (state, x, y) => { @@ -306,10 +318,10 @@ public async Task UpdateProductsPrices([FromBody] ProductPrice[] p changedPrices.AddRange(sourcePricesGroup); } } - await _pricingService.SavePricesAsync(changedPrices.ToArray()); + await _priceService.SaveChangesAsync(changedPrices); if (!deletedPrices.IsNullOrEmpty()) { - await _pricingService.DeletePricesAsync(deletedPrices.Select(x => x.Id).ToArray()); + await _priceService.DeleteAsync(deletedPrices.Select(x => x.Id).ToList()); } return NoContent(); } @@ -331,8 +343,8 @@ public Task UpdateProductPrices([FromBody] ProductPrice productPri [Route("api/catalog/products/{productId}/pricelists")] public async Task> GetProductPriceLists(string productId) { - var productPrices = (await _pricingSearchService.SearchPricesAsync(new PricesSearchCriteria { Take = int.MaxValue, ProductId = productId })).Results; - var priceLists = (await _pricingSearchService.SearchPricelistsAsync(new PricelistSearchCriteria { Take = int.MaxValue })).Results; + var productPrices = (await _priceSearchService.SearchNoCloneAsync(new PricesSearchCriteria { Take = int.MaxValue, ProductId = productId })).Results; + var priceLists = (await _pricelistSearchService.SearchAsync(new PricelistSearchCriteria { Take = int.MaxValue })).Results; foreach (var pricelist in priceLists) { pricelist.Prices = productPrices.Where(x => x.PricelistId == pricelist.Id).ToList(); @@ -348,7 +360,7 @@ public async Task> GetProductPriceLists(string product [Route("api/pricing/pricelists/{id}")] public async Task> GetPriceListById(string id) { - var pricelist = (await _pricingService.GetPricelistsByIdAsync(new[] { id })).FirstOrDefault(); + var pricelist = await _pricelistService.GetNoCloneAsync(id); return Ok(pricelist); } @@ -360,7 +372,7 @@ public async Task> GetPriceListById(string id) [Route("api/pricing/pricelistsshort/{id}")] public async Task> GetPriceListInShortById(string id) { - var pricelist = (await _pricingService.GetPricelistsByIdAsync(new[] { id }, nameof(PriceListResponseGroup.NoDetails))).FirstOrDefault(); + var pricelist = await _pricelistService.GetNoCloneAsync(id, PriceListResponseGroup.NoDetails.ToString()); return Ok(pricelist); } @@ -380,7 +392,7 @@ public async Task> CreatePriceList([FromBody] Pricelist return BadRequest(validationResult.Errors.Select(x => x.ErrorMessage)); } - await _pricingService.SavePricelistsAsync(new[] { priceList }); + await _pricelistService.SaveChangesAsync(new[] { priceList }); return Ok(priceList); } @@ -393,7 +405,7 @@ public async Task> CreatePriceList([FromBody] Pricelist [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)] public async Task UpdatePriceList([FromBody] Pricelist priceList) { - await _pricingService.SavePricelistsAsync(new[] { priceList }); + await _pricelistService.SaveChangesAsync(new[] { priceList }); return NoContent(); } @@ -409,7 +421,7 @@ public async Task UpdatePriceList([FromBody] Pricelist priceList) [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)] public async Task DeleteAssignments(string[] ids) { - await _pricingService.DeletePricelistsAssignmentsAsync(ids); + await _pricelistAssignmentService.DeleteAsync(ids); return NoContent(); } @@ -430,15 +442,15 @@ public async Task DeleteFilteredAssignments([FromQuery] PricelistA criteria = new PricelistAssignmentsSearchCriteria(); } - var result = await _pricingSearchService.SearchPricelistAssignmentsAsync(criteria); + var result = await _pricelistAssignmentSearchService.SearchNoCloneAsync(criteria); - var pricelistAssignmentsIds = result.Results.Select(x => x.Id); + var pricelistAssignmentsIds = result.Results.Select(x => x.Id).ToList(); - const int BATCH_SIZE = 20; - for (var skip = 0; skip < pricelistAssignmentsIds.Count(); skip += BATCH_SIZE) + const int batchSize = 20; + for (var skip = 0; skip < pricelistAssignmentsIds.Count; skip += batchSize) { - var batch = pricelistAssignmentsIds.Skip(skip).Take(BATCH_SIZE); - await _pricingService.DeletePricelistsAssignmentsAsync(batch.ToArray()); + var idsBatch = pricelistAssignmentsIds.Skip(skip).Take(batchSize).ToList(); + await _pricelistAssignmentService.DeleteAsync(idsBatch); } return NoContent(); @@ -456,8 +468,16 @@ public async Task DeleteFilteredAssignments([FromQuery] PricelistA [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)] public async Task DeleteProductPrices(string pricelistId, string[] productIds) { - var result = await _pricingSearchService.SearchPricesAsync(new PricesSearchCriteria { PriceListId = pricelistId, ProductIds = productIds, Take = int.MaxValue }); - await _pricingService.DeletePricesAsync(result.Results.Select(x => x.Id).ToArray()); + var searchCriteria = new PricesSearchCriteria + { + PriceListId = pricelistId, + ProductIds = productIds, + Take = int.MaxValue, + }; + + var searchResult = await _priceSearchService.SearchNoCloneAsync(searchCriteria); + await _priceService.DeleteAsync(searchResult.Results.Select(x => x.Id).ToList()); + return NoContent(); } @@ -472,7 +492,7 @@ public async Task DeleteProductPrices(string pricelistId, string[] [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)] public async Task DeleteProductPrice(string[] priceIds) { - await _pricingService.DeletePricesAsync(priceIds); + await _priceService.DeleteAsync(priceIds); return NoContent(); } @@ -487,7 +507,7 @@ public async Task DeleteProductPrice(string[] priceIds) [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)] public async Task DeletePricelists(string[] ids) { - await _pricingService.DeletePricelistsAsync(ids); + await _pricelistService.DeleteAsync(ids); return NoContent(); } diff --git a/src/VirtoCommerce.PricingModule.Web/Module.cs b/src/VirtoCommerce.PricingModule.Web/Module.cs index 5423861c..5a5250e8 100644 --- a/src/VirtoCommerce.PricingModule.Web/Module.cs +++ b/src/VirtoCommerce.PricingModule.Web/Module.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading.Tasks; using FluentValidation; using Microsoft.AspNetCore.Authorization; @@ -17,7 +16,6 @@ using VirtoCommerce.Platform.Core.Bus; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.ExportImport; -using VirtoCommerce.Platform.Core.GenericCrud; using VirtoCommerce.Platform.Core.Modularity; using VirtoCommerce.Platform.Core.Security; using VirtoCommerce.Platform.Core.Settings; @@ -28,7 +26,6 @@ using VirtoCommerce.PricingModule.Core.Events; using VirtoCommerce.PricingModule.Core.Model; using VirtoCommerce.PricingModule.Core.Model.Conditions; -using VirtoCommerce.PricingModule.Core.Model.Search; using VirtoCommerce.PricingModule.Core.Services; using VirtoCommerce.PricingModule.Data.Common; using VirtoCommerce.PricingModule.Data.ExportImport; @@ -38,27 +35,21 @@ using VirtoCommerce.PricingModule.Data.Repositories; using VirtoCommerce.PricingModule.Data.Search; using VirtoCommerce.PricingModule.Data.Services; -using VirtoCommerce.PricingModule.Data.Services.Search; using VirtoCommerce.PricingModule.Data.SqlServer; using VirtoCommerce.PricingModule.Data.Validators; -#pragma warning disable CS0618 // Allow to use obsoleted - namespace VirtoCommerce.PricingModule.Web { public class Module : IModule, IExportSupport, IImportSupport, IHasConfiguration { private IApplicationBuilder _applicationBuilder; - public IConfiguration Configuration { get; set; } - - - #region IModule Members public ManifestModuleInfo ModuleInfo { get; set; } + public IConfiguration Configuration { get; set; } public void Initialize(IServiceCollection serviceCollection) { - serviceCollection.AddDbContext((provider, options) => + serviceCollection.AddDbContext(options => { var databaseProvider = Configuration.GetValue("DatabaseProvider", "SqlServer"); var connectionString = Configuration.GetConnectionString(ModuleInfo.Id) ?? Configuration.GetConnectionString("VirtoCommerce"); @@ -80,14 +71,12 @@ public void Initialize(IServiceCollection serviceCollection) serviceCollection.AddTransient(); serviceCollection.AddTransient>(provider => () => provider.CreateScope().ServiceProvider.GetRequiredService()); serviceCollection.AddTransient(); - serviceCollection.AddTransient, PricelistAssignmentSearchService>(); - serviceCollection.AddTransient, PricelistSearchService>(); - serviceCollection.AddTransient, PriceSearchService>(); - serviceCollection.AddTransient, PricelistAssignmentService>(); - serviceCollection.AddTransient, PricelistService>(); - serviceCollection.AddTransient, PriceService>(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); serviceCollection.AddTransient(); serviceCollection.AddTransient(); serviceCollection.AddTransient(); @@ -98,11 +87,8 @@ public void Initialize(IServiceCollection serviceCollection) serviceCollection.AddTransient(); serviceCollection.AddTransient>, PricelistAssignmentsValidator>(); serviceCollection.AddTransient, PriceListValidator>(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); var requirements = new IAuthorizationRequirement[] @@ -130,14 +116,8 @@ public void PostInitialize(IApplicationBuilder appBuilder) var settingsRegistrar = appBuilder.ApplicationServices.GetRequiredService(); settingsRegistrar.RegisterSettings(ModuleConstants.Settings.AllSettings, ModuleInfo.Id); - var modulePermissions = ModuleConstants.Security.Permissions.AllPermissions.Select(p => new Permission - { - Name = p, - GroupName = "Pricing", - ModuleId = ModuleInfo.Id - }).ToArray(); var permissionsRegistrar = appBuilder.ApplicationServices.GetRequiredService(); - permissionsRegistrar.RegisterPermissions(modulePermissions); + permissionsRegistrar.RegisterPermissions(ModuleInfo.Id, "Pricing", ModuleConstants.Security.Permissions.AllPermissions); using (var serviceScope = appBuilder.ApplicationServices.CreateScope()) { @@ -151,37 +131,37 @@ public void PostInitialize(IApplicationBuilder appBuilder) } //Subscribe for Search configuration changes - var inProcessBus = appBuilder.ApplicationServices.GetService(); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); + var handlerRegistrar = appBuilder.ApplicationServices.GetService(); + handlerRegistrar.RegisterHandler(async (message, _) => await appBuilder.ApplicationServices.GetService().Handle(message)); //Configure Search var moduleConfigurator = appBuilder.ApplicationServices.GetService(); - moduleConfigurator.ConfigureSearchAsync(); + moduleConfigurator.ConfigureSearchAsync().GetAwaiter().GetResult(); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); + handlerRegistrar.RegisterHandler(async (message, _) => await appBuilder.ApplicationServices.GetService().Handle(message)); + handlerRegistrar.RegisterHandler(async (message, _) => await appBuilder.ApplicationServices.GetService().Handle(message)); + handlerRegistrar.RegisterHandler(async (message, _) => await appBuilder.ApplicationServices.GetService().Handle(message)); foreach (var conditionTree in AbstractTypeFactory.TryCreateInstance().Traverse(x => x.AvailableChildren)) { AbstractTypeFactory.RegisterType(conditionTree.GetType()); } - var registrar = appBuilder.ApplicationServices.GetService(); + var exportTypesRegistrar = appBuilder.ApplicationServices.GetService(); - registrar.RegisterType( + exportTypesRegistrar.RegisterType( ExportedTypeDefinitionBuilder.Build() .WithDataSourceFactory(appBuilder.ApplicationServices.GetService()) .WithMetadata(typeof(ExportablePrice).GetPropertyNames()) .WithTabularMetadata(typeof(TabularPrice).GetPropertyNames())); - registrar.RegisterType( + exportTypesRegistrar.RegisterType( ExportedTypeDefinitionBuilder.Build() .WithDataSourceFactory(appBuilder.ApplicationServices.GetService()) .WithMetadata(typeof(ExportablePricelist).GetPropertyNames()) .WithTabularMetadata(typeof(TabularPricelist).GetPropertyNames())); - registrar.RegisterType( + exportTypesRegistrar.RegisterType( ExportedTypeDefinitionBuilder.Build() .WithDataSourceFactory(appBuilder.ApplicationServices.GetService()) .WithMetadata(typeof(ExportablePricelistAssignment).GetPropertyNames()) @@ -193,10 +173,6 @@ public void Uninstall() // no need to perform actions for now (Comment to remove Sonar warning) } - #endregion - - #region ISupportExportImportModule Members - public Task ExportAsync(Stream outStream, ExportImportOptions options, Action progressCallback, ICancellationToken cancellationToken) { @@ -210,7 +186,5 @@ public Task ImportAsync(Stream inputStream, ExportImportOptions options, Action< var importJob = _applicationBuilder.ApplicationServices.GetRequiredService(); return importJob.DoImportAsync(inputStream, progressCallback, cancellationToken); } - - #endregion } } diff --git a/src/VirtoCommerce.PricingModule.Web/VirtoCommerce.PricingModule.Web.csproj b/src/VirtoCommerce.PricingModule.Web/VirtoCommerce.PricingModule.Web.csproj index cae8a696..e5ae9b76 100644 --- a/src/VirtoCommerce.PricingModule.Web/VirtoCommerce.PricingModule.Web.csproj +++ b/src/VirtoCommerce.PricingModule.Web/VirtoCommerce.PricingModule.Web.csproj @@ -2,18 +2,18 @@ net6.0 true - Library + 1591 False + Library - 1701;1702;1705;1591 Library - - false + + false @@ -24,9 +24,7 @@ - - - + diff --git a/src/VirtoCommerce.PricingModule.Web/module.manifest b/src/VirtoCommerce.PricingModule.Web/module.manifest index 06031317..eae953ff 100644 --- a/src/VirtoCommerce.PricingModule.Web/module.manifest +++ b/src/VirtoCommerce.PricingModule.Web/module.manifest @@ -1,9 +1,18 @@ - + VirtoCommerce.Pricing 3.400.0 - 3.286.0 + + 3.400.0 + + + + + + + + Pricing module Robust pricing management functionality based on price list and dynamic evaluation @@ -19,13 +28,6 @@ price pricelist merchandise VirtoCommerce.PricingModule.Web.dll VirtoCommerce.PricingModule.Web.Module, VirtoCommerce.PricingModule.Web - - - - - - - commerce diff --git a/tests/VirtoCommerce.PricingModule.Test/ExportImport2Test.cs b/tests/VirtoCommerce.PricingModule.Test/ExportImport2Test.cs index 34c9bc21..c33b0d0f 100644 --- a/tests/VirtoCommerce.PricingModule.Test/ExportImport2Test.cs +++ b/tests/VirtoCommerce.PricingModule.Test/ExportImport2Test.cs @@ -34,11 +34,11 @@ public Task PriceJsonExport() //Arrange IKnownExportTypesRegistrar registrar = new KnownExportTypesService(); - var searchServiceMock = new Mock(); - searchServiceMock.Setup(x => x.SearchPricesAsync(It.Is(y => y.Skip == 0))).ReturnsAsync(GetTestPriceResult()); - searchServiceMock.Setup(x => x.SearchPricesAsync(It.Is(y => y.Skip > 0))).ReturnsAsync(new PriceSearchResult()); + var priceSearchServiceMock = new Mock(); + priceSearchServiceMock.Setup(x => x.SearchAsync(It.Is(y => y.Skip == 0), false)).ReturnsAsync(GetTestPriceResult()); + priceSearchServiceMock.Setup(x => x.SearchAsync(It.Is(y => y.Skip > 0), false)).ReturnsAsync(new PriceSearchResult()); - var priceServiceMock = new Mock(); + var pricelistServiceMock = new Mock(); var itemServiceMock = new Mock(); @@ -46,7 +46,15 @@ public Task PriceJsonExport() var resolver = (IKnownExportTypesResolver)registrar; registrar.RegisterType(ExportedTypeDefinitionBuilder.Build() - .WithDataSourceFactory(new PricingExportPagedDataSourceFactory(searchServiceMock.Object, priceServiceMock.Object, itemServiceMock.Object, new Mock().Object)) + .WithDataSourceFactory(new PricingExportPagedDataSourceFactory( + priceSearchServiceMock.Object, + new Mock().Object, + new Mock().Object, + pricelistServiceMock.Object, + new Mock().Object, + new Mock().Object, + itemServiceMock.Object, + new Mock().Object)) .WithMetadata(metadata)); var includedPropertyNames = new string[] { "Currency", "ProductId", "Sale", "List", "MinQuantity", "StartDate", "EndDate", "EffectiveValue" }; @@ -102,22 +110,29 @@ public Task PricelistJsonExport() //Arrange IKnownExportTypesRegistrar registrar = new KnownExportTypesService(); - var searchServiceMock = new Mock(); - searchServiceMock.Setup(x => x.SearchPricelistsAsync(It.Is(y => y.Skip == 0))).ReturnsAsync(GetTestPricelistResult()); - searchServiceMock.Setup(x => x.SearchPricelistsAsync(It.Is(y => y.Skip > 0))).ReturnsAsync(new PricelistSearchResult()); + var pricelistSearchServiceMock = new Mock(); + pricelistSearchServiceMock.Setup(x => x.SearchAsync(It.Is(y => y.Skip == 0), false)).ReturnsAsync(GetTestPricelistResult()); + pricelistSearchServiceMock.Setup(x => x.SearchAsync(It.Is(y => y.Skip > 0), false)).ReturnsAsync(new PricelistSearchResult()); - searchServiceMock.Setup(x => x.SearchPricesAsync(It.IsAny())).ReturnsAsync(new PriceSearchResult() + var priceSearchServiceMock = new Mock(); + priceSearchServiceMock.Setup(x => x.SearchAsync(It.IsAny(), false)).ReturnsAsync(new PriceSearchResult() { TotalCount = 0, Results = new List(), }); - var priceServiceMock = new Mock(); - var metadata = typeof(ExportablePricelist).GetPropertyNames(); var resolver = (IKnownExportTypesResolver)registrar; registrar.RegisterType(ExportedTypeDefinitionBuilder.Build() - .WithDataSourceFactory(new PricingExportPagedDataSourceFactory(searchServiceMock.Object, priceServiceMock.Object, new Mock().Object, new Mock().Object)) + .WithDataSourceFactory(new PricingExportPagedDataSourceFactory( + priceSearchServiceMock.Object, + new Mock().Object, + pricelistSearchServiceMock.Object, + new Mock().Object, + new Mock().Object, + new Mock().Object, + new Mock().Object, + new Mock().Object)) .WithMetadata(metadata)); var exportProviderFactories = new[] { @@ -174,17 +189,25 @@ public Task PricelistAssignmentJsonExport() { IKnownExportTypesRegistrar registrar = new KnownExportTypesService(); - var searchServiceMock = new Mock(); - searchServiceMock.Setup(x => x.SearchPricelistAssignmentsAsync(It.Is(y => y.Skip == 0))).ReturnsAsync(GetPricelistAssignmentSearchResult()); - searchServiceMock.Setup(x => x.SearchPricelistAssignmentsAsync(It.Is(y => y.Skip > 0))).ReturnsAsync(new PricelistAssignmentSearchResult()); + var pricelistAssignmentSearchService = new Mock(); + pricelistAssignmentSearchService.Setup(x => x.SearchAsync(It.Is(y => y.Skip == 0), false)).ReturnsAsync(GetPricelistAssignmentSearchResult()); + pricelistAssignmentSearchService.Setup(x => x.SearchAsync(It.Is(y => y.Skip > 0), false)).ReturnsAsync(new PricelistAssignmentSearchResult()); - var priceServiceMock = new Mock(); + var pricelistServiceMock = new Mock(); var catalogServiceMock = new Mock(); var metadata = typeof(ExportablePricelistAssignment).GetPropertyNames(); var resolver = (IKnownExportTypesResolver)registrar; registrar.RegisterType(ExportedTypeDefinitionBuilder.Build() - .WithDataSourceFactory(new PricingExportPagedDataSourceFactory(searchServiceMock.Object, priceServiceMock.Object, new Mock().Object, catalogServiceMock.Object)) + .WithDataSourceFactory(new PricingExportPagedDataSourceFactory( + new Mock().Object, + new Mock().Object, + new Mock().Object, + pricelistServiceMock.Object, + pricelistAssignmentSearchService.Object, + new Mock().Object, + new Mock().Object, + catalogServiceMock.Object)) .WithMetadata(metadata)); var exportProviderFactories = new[] { @@ -246,17 +269,25 @@ public Task PriceCsvExport() var resolver = (IKnownExportTypesResolver)registrar; - var searchServiceMock = new Mock(); - searchServiceMock.Setup(x => x.SearchPricesAsync(It.Is(y => y.Skip == 0))).ReturnsAsync(GetTestPriceResult()); - searchServiceMock.Setup(x => x.SearchPricesAsync(It.Is(y => y.Skip > 0))).ReturnsAsync(new PriceSearchResult()); + var priceSearchServiceMock = new Mock(); + priceSearchServiceMock.Setup(x => x.SearchAsync(It.Is(y => y.Skip == 0), false)).ReturnsAsync(GetTestPriceResult()); + priceSearchServiceMock.Setup(x => x.SearchAsync(It.Is(y => y.Skip > 0), false)).ReturnsAsync(new PriceSearchResult()); - var priceServiceMock = new Mock(); + var pricelistServiceMock = new Mock(); var itemServiceMock = new Mock(); var metadata = typeof(ExportablePrice).GetPropertyNames(); registrar.RegisterType(ExportedTypeDefinitionBuilder.Build() - .WithDataSourceFactory(new PricingExportPagedDataSourceFactory(searchServiceMock.Object, priceServiceMock.Object, itemServiceMock.Object, new Mock().Object)) + .WithDataSourceFactory(new PricingExportPagedDataSourceFactory( + priceSearchServiceMock.Object, + new Mock().Object, + new Mock().Object, + pricelistServiceMock.Object, + new Mock().Object, + new Mock().Object, + itemServiceMock.Object, + new Mock().Object)) .WithMetadata(metadata) .WithTabularMetadata(typeof(TabularPrice).GetPropertyNames())); diff --git a/tests/VirtoCommerce.PricingModule.Test/ExportImportTest.cs b/tests/VirtoCommerce.PricingModule.Test/ExportImportTest.cs index 71efc7d4..e2dee821 100644 --- a/tests/VirtoCommerce.PricingModule.Test/ExportImportTest.cs +++ b/tests/VirtoCommerce.PricingModule.Test/ExportImportTest.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Moq; @@ -19,40 +20,38 @@ public async Task TestArbitraryImport() { var data = GetSampleDataStream(); - var pricingService = GetPricingService(); - - var settingsManager = GetSettingsManager(); + var priceService = new Mock(); + var pricelistService = new Mock(); + var pricelistAssignmentService = new Mock(); + var settingsManager = new Mock(); settingsManager.Setup(s => s.GetObjectSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(new ObjectSettingEntry { Value = 2 }); - var importProcessor = GetImportExportProcessor(pricingService.Object, settingsManager.Object); + var importProcessor = GetImportExportProcessor(priceService.Object, pricelistService.Object, pricelistAssignmentService.Object, settingsManager.Object); var cancellationTokenMock = new Mock(); await importProcessor.DoImportAsync(data, GetProgressCallback, cancellationTokenMock.Object); - pricingService.Verify(p => p.SavePricesAsync(It.IsAny()), Times.Exactly(2)); - pricingService.Verify(p => p.SavePricelistsAsync(It.IsAny()), Times.Exactly(1)); - pricingService.Verify(p => p.SavePricelistAssignmentsAsync(It.IsAny()), Times.Exactly(1)); - } - - private PricingExportImport GetImportExportProcessor(IPricingService pricingService, ISettingsManager settingsManager) - { - return new PricingExportImport(pricingService, GetPricingSearchService(), settingsManager, GetJsonSerializer()); - } - - private Mock GetPricingService() - { - return new Mock(); - } - - private IPricingSearchService GetPricingSearchService() - { - return new Mock().Object; + priceService.Verify(p => p.SaveChangesAsync(It.IsAny>()), Times.Exactly(2)); + pricelistService.Verify(p => p.SaveChangesAsync(It.IsAny>()), Times.Exactly(1)); + pricelistAssignmentService.Verify(p => p.SaveChangesAsync(It.IsAny>()), Times.Exactly(1)); } - private Mock GetSettingsManager() + private PricingExportImport GetImportExportProcessor( + IPriceService priceService, + IPricelistService pricelistService, + IPricelistAssignmentService pricelistAssignmentService, + ISettingsManager settingsManager) { - return new Mock(); + return new PricingExportImport( + new Mock().Object, + priceService, + new Mock().Object, + pricelistService, + new Mock().Object, + pricelistAssignmentService, + settingsManager, + GetJsonSerializer()); } private Stream GetStreamFromString(string value) diff --git a/tests/VirtoCommerce.PricingModule.Test/PriceScenarios.cs b/tests/VirtoCommerce.PricingModule.Test/PriceScenarios.cs index 0426e9b8..cc477391 100644 --- a/tests/VirtoCommerce.PricingModule.Test/PriceScenarios.cs +++ b/tests/VirtoCommerce.PricingModule.Test/PriceScenarios.cs @@ -12,11 +12,8 @@ using VirtoCommerce.PricingModule.Data.Repositories; using VirtoCommerce.PricingModule.Data.Search; using VirtoCommerce.PricingModule.Data.Services; -using VirtoCommerce.PricingModule.Data.Validators; using Xunit; -#pragma warning disable CS0618 // Allow to use obsoleted - namespace VirtoCommerce.PricingModule.Test { public class PriceScenarios @@ -31,7 +28,7 @@ public void Get_document_changes_from_multiple_data_sources() new OperationLogEntity { ModifiedDate = new DateTime(2018, 11, 01), ObjectId = "3", ObjectType = nameof(PriceEntity) }, }; - var mockPrices = new PriceEntity[] { + var mockPrices = new[] { //Without from/till dates (unbounded) new PriceEntity { Id = "1", ProductId = "1" }, //Without from date (unbounded) @@ -182,10 +179,10 @@ public void Can_return_price_from_many_prices_with_start_and_end_date() var evalContext = new PriceEvaluationContext { ProductIds = new[] { "ProductId" }, - Pricelists = new [] { pricelist } + Pricelists = new[] { pricelist } }; - var mockPrices = new PriceEntity[] { + var mockPrices = new[] { // Unbounded past. new PriceEntity { Id = "1", List = 1, EndDate = new DateTime(2018, 09, 10), PricelistId = "List1" , ProductId = "ProductId" }, // Bounded past. @@ -203,12 +200,7 @@ public void Can_return_price_from_many_prices_with_start_and_end_date() var mockRepository = new Mock(); mockRepository.SetupGet(x => x.Prices).Returns(mockPrices.Object); - var service = new PricingServiceImpl(new PricelistAssignmentService(() => mockRepository.Object, null, null, new PricelistAssignmentsValidator()), - new PricelistService(() => mockRepository.Object, null, null), - new PriceService(() => mockRepository.Object, null, null, null), - new PricingEvaluatorService( - () => mockRepository.Object, null, null, null, - new DefaultPricingPriorityFilterPolicy())); + var service = new PricingEvaluatorService(() => mockRepository.Object, null, null, null, new DefaultPricingPriorityFilterPolicy()); // Eval with date and no matches, this should result in default price. evalContext.CertainDate = new DateTime(2018, 09, 20); @@ -241,7 +233,7 @@ public void Can_return_price_from_many_prices_with_start_and_end_date() Assert.Equal(4, prices.Single().List); // Eval without date, should result in unbounded future price. - // This is also a backwards compatibilty test. + // This is also a backwards compatibility test. // CertainDate was not used in previous price evaluation. Default to 'now' behaviour. evalContext.CertainDate = null; prices = service.EvaluateProductPricesAsync(evalContext).GetAwaiter().GetResult(); diff --git a/tests/VirtoCommerce.PricingModule.Test/PricingServiceImplUnitTests.cs b/tests/VirtoCommerce.PricingModule.Test/PricingServiceImplUnitTests.cs index d4d6de4c..b602572c 100644 --- a/tests/VirtoCommerce.PricingModule.Test/PricingServiceImplUnitTests.cs +++ b/tests/VirtoCommerce.PricingModule.Test/PricingServiceImplUnitTests.cs @@ -6,9 +6,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; -using VirtoCommerce.CatalogModule.Core.Services; using VirtoCommerce.Platform.Caching; -using VirtoCommerce.Platform.Core.Caching; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.Domain; using VirtoCommerce.Platform.Core.Events; @@ -19,37 +17,38 @@ using VirtoCommerce.PricingModule.Data.Validators; using Xunit; -#pragma warning disable CS0618 // Allow to use obsoleted - namespace VirtoCommerce.PricingModule.Test { public class PricingServiceImplUnitTests { - private readonly Mock _unitOfWorkMock; private readonly Mock _repositoryMock; - private readonly Mock _productServiceMock; - private readonly Mock> _loggerMock; - private readonly Mock _eventPublisherMock; - private readonly Mock _pricingPriorityFilterPolicyMock; + private readonly PricelistAssignmentService _pricelistAssignmentService; + private readonly PricelistService _pricelistService; + private readonly PriceService _priceService; public PricingServiceImplUnitTests() { - _unitOfWorkMock = new Mock(); + var unitOfWorkMock = new Mock(); _repositoryMock = new Mock(); - _productServiceMock = new Mock(); - _loggerMock = new Mock>(); - _eventPublisherMock = new Mock(); - _pricingPriorityFilterPolicyMock = new Mock(); + _repositoryMock.Setup(ss => ss.UnitOfWork).Returns(unitOfWorkMock.Object); + + var memoryCache = new MemoryCache(Options.Create(new MemoryCacheOptions())); + var platformMemoryCache = new PlatformMemoryCache(memoryCache, Options.Create(new CachingOptions()), new Mock>().Object); + + var eventPublisherMock = new Mock(); + + _pricelistAssignmentService = new PricelistAssignmentService(() => _repositoryMock.Object, platformMemoryCache, eventPublisherMock.Object, new PricelistAssignmentsValidator()); + _pricelistService = new PricelistService(() => _repositoryMock.Object, platformMemoryCache, eventPublisherMock.Object); + _priceService = new PriceService(() => _repositoryMock.Object, platformMemoryCache, eventPublisherMock.Object, _pricelistService); } [Fact] - public async Task GetByIdsAsync_GetThenSavePrice_ReturnCachedPrice() + public async Task GetAsync_GetThenSavePrice_ReturnCachedPrice() { //Arrange var id = Guid.NewGuid().ToString(); var newPrice = new Price { Id = id }; var newPriceEntity = AbstractTypeFactory.TryCreateInstance().FromModel(newPrice, new PrimaryKeyResolvingMap()); - var service = GetPricingServiceImplWithPlatformMemoryCache(); _repositoryMock.Setup(x => x.Add(newPriceEntity)) .Callback(() => { @@ -59,25 +58,24 @@ public async Task GetByIdsAsync_GetThenSavePrice_ReturnCachedPrice() _repositoryMock.Setup(o => o.GetPricesByIdsAsync(new[] { id })) .ReturnsAsync(new List()); - _repositoryMock.Setup(o => o.GetPricelistByIdsAsync(It.IsAny>(), null)) + _repositoryMock.Setup(o => o.GetPricelistByIdsAsync(It.IsAny>(), null)) .ReturnsAsync(new List()); //Act - var nullPrice = await service.GetPricesByIdAsync(new[] { id }); - await service.SavePricesAsync(new[] { newPrice }); - var price = await service.GetPricesByIdAsync(new[] { id }); + var nullPrice = await _priceService.GetByIdAsync(id); + await _priceService.SaveChangesAsync(new[] { newPrice }); + var price = await _priceService.GetByIdAsync(id); //Assert Assert.NotEqual(nullPrice, price); } [Fact] - public async Task GetByIdsAsync_GetThenSavePricelist_ReturnCachedPricelist() + public async Task GetAsync_GetThenSavePricelist_ReturnCachedPricelist() { //Arrange var id = Guid.NewGuid().ToString(); var newPricelist = new Pricelist { Id = id }; var newPricelistEntity = AbstractTypeFactory.TryCreateInstance().FromModel(newPricelist, new PrimaryKeyResolvingMap()); - var service = GetPricingServiceImplWithPlatformMemoryCache(); _repositoryMock.Setup(x => x.Add(newPricelistEntity)) .Callback(() => { @@ -89,16 +87,16 @@ public async Task GetByIdsAsync_GetThenSavePricelist_ReturnCachedPricelist() .ReturnsAsync(new List()); //Act - var nullPricelist = await service.GetPricelistsByIdAsync(new[] { id }); - await service.SavePricelistsAsync(new[] { newPricelist }); - var pricelist = await service.GetPricelistsByIdAsync(new[] { id }); + var nullPricelist = await _pricelistService.GetByIdAsync(id); + await _pricelistService.SaveChangesAsync(new[] { newPricelist }); + var pricelist = await _pricelistService.GetByIdAsync(id); //Assert Assert.NotEqual(nullPricelist, pricelist); } [Fact] - public async Task GetByIdsAsync_GetThenSavePricelistAssignment_ReturnCachedPricelistAssignment() + public async Task GetAsync_GetThenSavePricelistAssignment_ReturnCachedPricelistAssignment() { //Arrange var id = Guid.NewGuid().ToString(); @@ -109,7 +107,6 @@ public async Task GetByIdsAsync_GetThenSavePricelistAssignment_ReturnCachedPrice }; var newPricelistAssignmentEntity = AbstractTypeFactory.TryCreateInstance().FromModel(newPricelistAssignment, new PrimaryKeyResolvingMap()); - var service = GetPricingServiceImplWithPlatformMemoryCache(); _repositoryMock.Setup(x => x.Add(newPricelistAssignmentEntity)) .Callback(() => { @@ -120,12 +117,12 @@ public async Task GetByIdsAsync_GetThenSavePricelistAssignment_ReturnCachedPrice _repositoryMock.Setup(o => o.GetPricelistAssignmentsByIdAsync(new[] { id })) .ReturnsAsync(new List()); //Act - var nullPricelistAssignment = await service.GetPricelistAssignmentsByIdAsync(new[] { id }); - await service.SavePricelistAssignmentsAsync(new[] { newPricelistAssignment }); - var PricelistAssignment = await service.GetPricelistAssignmentsByIdAsync(new[] { id }); + var nullPricelistAssignment = await _pricelistAssignmentService.GetByIdAsync(id); + await _pricelistAssignmentService.SaveChangesAsync(new[] { newPricelistAssignment }); + var pricelistAssignment = await _pricelistAssignmentService.GetByIdAsync(id); //Assert - Assert.NotEqual(nullPricelistAssignment, PricelistAssignment); + Assert.NotEqual(nullPricelistAssignment, pricelistAssignment); } [Fact] @@ -138,10 +135,8 @@ public Task SavePricelistAssignment_StoreAndCatalogNotNull_ValidationExceptionTh CatalogId = Guid.NewGuid().ToString(), }; - var service = GetPricingServiceImplWithPlatformMemoryCache(); - // Assert - return Assert.ThrowsAsync(() => service.SavePricelistAssignmentsAsync(new[] { newPricelistAssignment })); + return Assert.ThrowsAsync(() => _pricelistAssignmentService.SaveChangesAsync(new[] { newPricelistAssignment })); } [Fact] @@ -150,36 +145,8 @@ public Task SavePricelistAssignment_StoreAndCatalogNull_ValidationExceptionThrow //Arrange var newPricelistAssignment = new PricelistAssignment(); - var service = GetPricingServiceImplWithPlatformMemoryCache(); - // Assert - return Assert.ThrowsAsync(() => service.SavePricelistAssignmentsAsync(new[] { newPricelistAssignment })); - } - - - private PricingServiceImpl GetPricingServiceImplWithPlatformMemoryCache() - { - var memoryCache = new MemoryCache(Options.Create(new MemoryCacheOptions())); - var platformMemoryCache = new PlatformMemoryCache(memoryCache, Options.Create(new CachingOptions()), new Mock>().Object); - _repositoryMock.Setup(ss => ss.UnitOfWork).Returns(_unitOfWorkMock.Object); - - return GetPricingServiceImpl(platformMemoryCache, _repositoryMock.Object); - } - - private PricingServiceImpl GetPricingServiceImpl(IPlatformMemoryCache platformMemoryCache, IPricingRepository pricingRepository) - { - return new PricingServiceImpl( - new PricelistAssignmentService(() => pricingRepository, platformMemoryCache, _eventPublisherMock.Object, new PricelistAssignmentsValidator()), - new PricelistService(() => pricingRepository, platformMemoryCache, _eventPublisherMock.Object), - new PriceService(() => pricingRepository, platformMemoryCache, _eventPublisherMock.Object, new PricelistService(() => pricingRepository, platformMemoryCache, null)), - new PricingEvaluatorService( - () => pricingRepository, - _productServiceMock.Object, - _loggerMock.Object, - platformMemoryCache, - _pricingPriorityFilterPolicyMock.Object - ) - ); + return Assert.ThrowsAsync(() => _pricelistAssignmentService.SaveChangesAsync(new[] { newPricelistAssignment })); } } } diff --git a/tests/VirtoCommerce.PricingModule.Test/VirtoCommerce.PricingModule.Test.csproj b/tests/VirtoCommerce.PricingModule.Test/VirtoCommerce.PricingModule.Test.csproj index e169c890..05117a88 100644 --- a/tests/VirtoCommerce.PricingModule.Test/VirtoCommerce.PricingModule.Test.csproj +++ b/tests/VirtoCommerce.PricingModule.Test/VirtoCommerce.PricingModule.Test.csproj @@ -12,7 +12,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all