|
|
@@ -4,22 +4,34 @@ import com.alibaba.fastjson.JSON;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import shop.alien.entity.store.StoreCuisine;
|
|
|
import shop.alien.entity.store.StoreCuisineCategory;
|
|
|
import shop.alien.entity.store.StoreInfo;
|
|
|
+import shop.alien.entity.store.StoreProductDiscountRule;
|
|
|
import shop.alien.entity.store.StoreTable;
|
|
|
import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
|
|
|
import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
|
|
|
+import shop.alien.entity.store.vo.StoreCuisineWithPricesVO;
|
|
|
import shop.alien.mapper.StoreCuisineCategoryMapper;
|
|
|
import shop.alien.mapper.StoreCuisineMapper;
|
|
|
import shop.alien.mapper.StoreInfoMapper;
|
|
|
+import shop.alien.mapper.StoreProductDiscountRuleMapper;
|
|
|
import shop.alien.mapper.StoreTableMapper;
|
|
|
import shop.alien.dining.service.StoreInfoService;
|
|
|
+import shop.alien.dining.support.ProductDiscountPricingSupport;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -37,6 +49,7 @@ public class StoreInfoServiceImpl implements StoreInfoService {
|
|
|
private final StoreCuisineCategoryMapper storeCuisineCategoryMapper;
|
|
|
private final StoreCuisineMapper storeCuisineMapper;
|
|
|
private final StoreInfoMapper storeInfoMapper;
|
|
|
+ private final StoreProductDiscountRuleMapper storeProductDiscountRuleMapper;
|
|
|
|
|
|
@Override
|
|
|
public List<StoreTable> getTablesByStoreId(Integer storeId) {
|
|
|
@@ -124,18 +137,77 @@ public class StoreInfoServiceImpl implements StoreInfoService {
|
|
|
}
|
|
|
boolean filterByName = StringUtils.isNotBlank(keyword);
|
|
|
String keywordLower = filterByName ? keyword.trim().toLowerCase() : null;
|
|
|
+
|
|
|
+ List<StoreCuisine> flatForPricing = new ArrayList<>();
|
|
|
+ for (StoreCuisineCategory category : categories) {
|
|
|
+ Integer categoryId = category.getId();
|
|
|
+ allCuisines.stream()
|
|
|
+ .filter(c -> belongsToCategory(c, categoryId))
|
|
|
+ .filter(c -> !filterByName || (c.getName() != null && c.getName().toLowerCase().contains(keywordLower)))
|
|
|
+ .forEach(flatForPricing::add);
|
|
|
+ }
|
|
|
+ Map<Integer, BigDecimal> discountedByProductId = buildDiscountedPriceMap(storeId, flatForPricing);
|
|
|
+
|
|
|
List<CategoryWithCuisinesVO> result = new ArrayList<>();
|
|
|
for (StoreCuisineCategory category : categories) {
|
|
|
Integer categoryId = category.getId();
|
|
|
- List<StoreCuisine> cuisines = allCuisines.stream()
|
|
|
+ List<StoreCuisineWithPricesVO> cuisines = allCuisines.stream()
|
|
|
.filter(c -> belongsToCategory(c, categoryId))
|
|
|
.filter(c -> !filterByName || (c.getName() != null && c.getName().toLowerCase().contains(keywordLower)))
|
|
|
+ .map(c -> toCuisineWithPricesVo(c, discountedByProductId))
|
|
|
.collect(Collectors.toList());
|
|
|
result.add(new CategoryWithCuisinesVO(category, cuisines));
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 与门店 {@code StoreProductDiscountService} 同一套规则,按当前时刻算折后价(仅包含有命中的菜品 id)
|
|
|
+ */
|
|
|
+ private Map<Integer, BigDecimal> buildDiscountedPriceMap(Integer storeId, List<StoreCuisine> visibleCuisines) {
|
|
|
+ if (visibleCuisines == null || visibleCuisines.isEmpty()) {
|
|
|
+ return new HashMap<>();
|
|
|
+ }
|
|
|
+ Set<Integer> idSet = new HashSet<>();
|
|
|
+ Map<Integer, BigDecimal> basePriceByProduct = new HashMap<>();
|
|
|
+ for (StoreCuisine c : visibleCuisines) {
|
|
|
+ if (c.getId() == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (idSet.add(c.getId())) {
|
|
|
+ BigDecimal p = c.getTotalPrice() != null ? c.getTotalPrice() : BigDecimal.ZERO;
|
|
|
+ basePriceByProduct.put(c.getId(), p);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<Integer> productIds = new ArrayList<>(idSet);
|
|
|
+ if (productIds.isEmpty()) {
|
|
|
+ return new HashMap<>();
|
|
|
+ }
|
|
|
+ List<StoreProductDiscountRule> rules = storeProductDiscountRuleMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<StoreProductDiscountRule>()
|
|
|
+ .eq(StoreProductDiscountRule::getStoreId, storeId)
|
|
|
+ .eq(StoreProductDiscountRule::getStatus, 1)
|
|
|
+ .in(StoreProductDiscountRule::getProductId, productIds));
|
|
|
+ return ProductDiscountPricingSupport.resolveDiscountedPrices(
|
|
|
+ productIds,
|
|
|
+ basePriceByProduct,
|
|
|
+ LocalDateTime.now(),
|
|
|
+ rules);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static StoreCuisineWithPricesVO toCuisineWithPricesVo(StoreCuisine cuisine, Map<Integer, BigDecimal> discountedByProductId) {
|
|
|
+ Map<Integer, BigDecimal> disc = discountedByProductId == null ? Collections.emptyMap() : discountedByProductId;
|
|
|
+ StoreCuisineWithPricesVO vo = new StoreCuisineWithPricesVO();
|
|
|
+ BeanUtils.copyProperties(cuisine, vo);
|
|
|
+ BigDecimal original = cuisine.getTotalPrice() != null ? cuisine.getTotalPrice() : BigDecimal.ZERO;
|
|
|
+ vo.setOriginalPrice(original);
|
|
|
+ boolean hasRule = cuisine.getId() != null && disc.containsKey(cuisine.getId());
|
|
|
+ BigDecimal current = hasRule ? disc.get(cuisine.getId()) : original;
|
|
|
+ vo.setCurrentPrice(current);
|
|
|
+ vo.setHasActiveDiscount(hasRule);
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
private boolean belongsToCategory(StoreCuisine cuisine, Integer categoryId) {
|
|
|
String categoryIdsStr = cuisine.getCategoryIds();
|
|
|
if (StringUtils.isBlank(categoryIdsStr)) {
|