Untitled
unknown
plain_text
10 days ago
12 kB
2
Indexable
Never
package de.evobus.on.oncommerce.search.product.service; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Optional; import de.evobus.on.portal.visData.persistence.InternalVehicleInformationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import de.evobus.on.oncommerce.account.toolbox.AccountToolbox; import de.evobus.on.oncommerce.checkout.category.data.CategoryDTO; import de.evobus.on.oncommerce.checkout.category.facade.CategoryFacade; import de.evobus.on.oncommerce.commerce.CommerceBackend; import de.evobus.on.oncommerce.commerce.models.*; import de.evobus.on.oncommerce.core.configuration.CommerceConfigurations; import de.evobus.on.oncommerce.core.configuration.PriceMappingConfiguration; import de.evobus.on.oncommerce.core.data.ProductSearchCategoryFacetDTO; import de.evobus.on.oncommerce.core.data.ProductSearchFacetDTO; import de.evobus.on.oncommerce.core.data.ProductSearchResultDTO; import de.evobus.on.oncommerce.core.exception.ConfigurationException; import de.evobus.on.oncommerce.core.price.service.SapListPriceService; import de.evobus.on.oncommerce.core.price.strategy.SparePartPriceLookupStrategy; import de.evobus.on.oncommerce.core.price.type.PriceMapper; import de.evobus.on.oncommerce.core.service.AbstractCommerceService; import de.evobus.on.oncommerce.dealer.persistence.model.Dealer; import de.evobus.on.oncommerce.dealer.persistence.repositories.CustomerAddressDealerCustomerMappingRepository; import de.evobus.on.oncommerce.dealer.persistence.repositories.DealerCustomerMappingRepository; import de.evobus.on.oncommerce.model.enums.CartType; import de.evobus.on.oncommerce.product.strategy.SparePartAttributeLookupStrategy; import de.evobus.on.oncommerce.product.strategy.SparePartVisibilityStrategy; import de.evobus.on.oncommerce.search.product.service.mapper.ProductSearchResultMapper; import de.evobus.on.oncommerce.service.category.CategoryNotFoundException; import de.evobus.on.oncommerce.service.category.CategoryService; import de.evobus.on.portal.account.persistence.Account; import static de.evobus.on.oncommerce.OnCommerce.DefaultCategory.*; import static java.lang.Boolean.TRUE; @Slf4j @Service public class ProductSearchService extends AbstractCommerceService { private final CategoryFacade categoryFacade; private final CategoryService categoryService; private final CommerceConfigurations commerceConfiguration; private final ProductSearchResultMapper productSearchResultMapper; private final PriceMappingConfiguration priceMappingConfiguration; private final SapListPriceService sapListPriceService; private final PriceMapper priceMapper; private final String defaultCategory; private final AccountToolbox accountToolbox; private final InternalVehicleInformationService vehicleInformationService; @Autowired public ProductSearchService(final CommerceBackend commerceBackend, final CategoryService categoryService, final CategoryFacade categoryFacade, final ProductSearchResultMapper productSearchResultMapper, final DealerCustomerMappingRepository dealerCustomerMappingRepository, final CustomerAddressDealerCustomerMappingRepository customerAddressDealerCustomerMappingRepository, final CommerceConfigurations commerceConfiguration, final PriceMappingConfiguration priceMappingConfiguration, final SapListPriceService sapListPriceService, final PriceMapper priceMapper, final InternalVehicleInformationService vehicleInformationService, @Value("${oncommerce.default.category}") String defaultCategory, AccountToolbox accountToolbox) { super(commerceBackend, dealerCustomerMappingRepository, customerAddressDealerCustomerMappingRepository); this.categoryFacade = categoryFacade; this.categoryService = categoryService; this.productSearchResultMapper = productSearchResultMapper; this.commerceConfiguration = commerceConfiguration; this.priceMappingConfiguration = priceMappingConfiguration; this.sapListPriceService = sapListPriceService; this.priceMapper = priceMapper; this.vehicleInformationService = vehicleInformationService; this.defaultCategory = defaultCategory; this.accountToolbox = accountToolbox; } public ProductSearchResultDTO searchProducts(@NonNull final Account account, final String categoryKey, final String vin, final boolean hideEmptyCategories, @NonNull final SortDirection sortDirection, final String language, final long pageNo, final long limitPerPage, @NonNull final CartType cartType, @NonNull final boolean catalogueContext) { final List<CategoryDTO> allCategoryDTOs = fetchAllCategoriesAsDTOs(account, language); CategoryDTO searchCategory; final String vAfterModel = vehicleInformationService.getAftersalesModel(vin); searchCategory = getCategoryDTO(categoryKey, catalogueContext, allCategoryDTOs); final PagedProductResult pagedSearchResult = getCommerceBackend().products().fetchProducts(searchCategory.getCategoryId(), vAfterModel, sortDirection, language, pageNo * limitPerPage, limitPerPage); List<ProductSearchFacetDTO> productSearchFacetDTOs = new ArrayList<>(); productSearchFacetDTOs.add(createCategoryFacets(pagedSearchResult, hideEmptyCategories, allCategoryDTOs)); Optional<Dealer> optionalSelectedDealer = accountToolbox.getOptionalSelectedDealer(account); return productSearchResultMapper .mapToDTO(account, pagedSearchResult, productSearchFacetDTOs, language, categoryService.getLookupByIdMap(), new SparePartPriceLookupStrategy(getCommerceBackend(), optionalSelectedDealer, priceMappingConfiguration.getMapping(optionalSelectedDealer, accountToolbox.getSelectedCustomerQuietly(account)), sapListPriceService, priceMapper), new SparePartAttributeLookupStrategy(), new SparePartVisibilityStrategy(cartType, commerceConfiguration), searchCategory); } protected CategoryDTO getCategoryDTO(String categoryKey, boolean catalogueContext, List<CategoryDTO> allCategoryDTOs) { CategoryDTO searchCategory; if (catalogueContext) { searchCategory = determineDefaultSearchCategory(categoryKey, allCategoryDTOs); } else { searchCategory = determineSearchCategory(categoryKey, allCategoryDTOs); } return searchCategory; } private ProductSearchCategoryFacetDTO createCategoryFacets(@NonNull final PagedProductResult pagedResult, final boolean hideEmptyCategories, @NonNull final List<CategoryDTO> categoryDTOs) { for (TermStats term : pagedResult.getCategoryTermStats()) { updateCategoryProductCount(categoryDTOs, term.getTerm(), term.getProductCount()); } cumulateCategoryProductCounts(categoryDTOs); if (hideEmptyCategories) { removeEmptyCategories(categoryDTOs); } // Return only the STOREFRONT category // It is optional because it can happen that the found products are not assigned // to any category // inside the storefront category. Optional<CategoryDTO> optionalStorefrontCategoryDTO = categoryDTOs.stream() .filter(categoryDTO -> categoryDTO.getCategoryKey().equals(STOREFRONT.getKey())).findFirst(); ProductSearchCategoryFacetDTO.ProductSearchCategoryFacetDTOBuilder builder = ProductSearchCategoryFacetDTO.builder(); if (optionalStorefrontCategoryDTO.isPresent()) { builder.categories(optionalStorefrontCategoryDTO.get().getSubCategories()); } else { builder.categories(Collections.emptyList()); } return builder.build(); } private List<CategoryDTO> fetchAllCategoriesAsDTOs(@NonNull final Account account, final String language) { try { return categoryFacade.readCategory(account, ROOT.getKey(), true, false, false, language).getSubCategories(); } catch (CategoryNotFoundException exception) { LOGGER.error("Failed to retrieve complete category tree."); throw new RuntimeException("Failed to retrieve complete category tree.", exception); } } protected CategoryDTO determineSearchCategory(String categoryKey, List<CategoryDTO> allCategoryDTOs) { return fetchCategoryByKey(categoryKey, allCategoryDTOs).orElseGet(() -> fetchCategoryByKey(STOREFRONT.getKey(), allCategoryDTOs) .orElseThrow(() -> new ConfigurationException("Storefront category is missing!"))); } protected CategoryDTO determineDefaultSearchCategory(String categoryKey, List<CategoryDTO> allCategoryDTOs) { Optional<CategoryDTO> matchingCategory = fetchCategoryByKey(categoryKey, allCategoryDTOs); if (!matchingCategory.isPresent()) { matchingCategory = fetchCategoryByKey(this.defaultCategory, allCategoryDTOs); } return matchingCategory.orElseThrow(() -> new ConfigurationException("Default category is missing!")); } private Optional<CategoryDTO> fetchCategoryByKey(final String categoryKey, final List<CategoryDTO> allCategoryDTOs) { if (categoryKey != null) { for (CategoryDTO categoryDTO : allCategoryDTOs) { if (categoryDTO.getCategoryKey().equals(categoryKey)) { return Optional.of(categoryDTO); } Optional<CategoryDTO> optionalCategory = fetchCategoryByKey(categoryKey, categoryDTO.getSubCategories()); if (optionalCategory.isPresent()) { return optionalCategory; } } } return Optional.empty(); } private void updateCategoryProductCount(final List<CategoryDTO> categoryDTOs, final String categoryId, final Long productCount) { final ListIterator<CategoryDTO> categoryDTOListIterator = categoryDTOs.listIterator(); while (categoryDTOListIterator.hasNext()) { final CategoryDTO categoryDTO = categoryDTOListIterator.next(); if (categoryDTO.getCategoryId().equals(categoryId)) { categoryDTOListIterator.set(categoryDTO.toBuilder().hasProducts(true).productCount(productCount).build()); break; } else { updateCategoryProductCount(categoryDTO.getSubCategories(), categoryId, productCount); } } } private Long cumulateCategoryProductCounts(final List<CategoryDTO> categoryDTOs) { Long productCount = 0L; final ListIterator<CategoryDTO> categoryDTOListIterator = categoryDTOs.listIterator(); while (categoryDTOListIterator.hasNext()) { final CategoryDTO categoryDTO = categoryDTOListIterator.next(); final Long productCountOfThisCategory = (categoryDTO.getProductCount() != null ? categoryDTO.getProductCount() : 0L) + cumulateCategoryProductCounts(categoryDTO.getSubCategories()); categoryDTOListIterator.set( categoryDTO.toBuilder().hasProducts(productCountOfThisCategory > 0).productCount(productCountOfThisCategory).build()); productCount += productCountOfThisCategory; } return productCount; } private void removeEmptyCategories(final List<CategoryDTO> categoryDTOs) { final Iterator<CategoryDTO> categoryDTOIterator = categoryDTOs.iterator(); while (categoryDTOIterator.hasNext()) { final CategoryDTO categoryDTO = categoryDTOIterator.next(); if (!TRUE.equals(categoryDTO.getHasProducts())) { categoryDTOIterator.remove(); } else { removeEmptyCategories(categoryDTO.getSubCategories()); } } } }
Leave a Comment