|
|
@@ -1,137 +0,0 @@
|
|
|
-package com.cyksj.service.order.impl;
|
|
|
-
|
|
|
-import cn.hutool.core.collection.CollUtil;
|
|
|
-import cn.hutool.core.util.StrUtil;
|
|
|
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
-import com.cyksj.common.exception.BusinessRuntimeException;
|
|
|
-import com.cyksj.common.util.Jsons;
|
|
|
-import com.cyksj.model.dto.MultiQuantitySkuConfig;
|
|
|
-import com.cyksj.model.entity.SysConfig;
|
|
|
-import com.cyksj.redis.RedisService;
|
|
|
-import com.cyksj.service.order.MultiQuantityOrderConfigService;
|
|
|
-import com.cyksj.service.sys.SysConfigService;
|
|
|
-import lombok.RequiredArgsConstructor;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-
|
|
|
-import java.util.Collections;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Optional;
|
|
|
-
|
|
|
-@Slf4j
|
|
|
-@Service
|
|
|
-@RequiredArgsConstructor
|
|
|
-public class MultiQuantityOrderConfigServiceImpl implements MultiQuantityOrderConfigService {
|
|
|
-
|
|
|
- private static final int ABSOLUTE_MAX_NUM = 100;
|
|
|
-
|
|
|
- private static final long CONFIG_CACHE_SECONDS = 300L;
|
|
|
-
|
|
|
- private volatile String cachedConfigValue;
|
|
|
-
|
|
|
- private volatile Map<Long, MultiQuantitySkuConfig> cachedConfigMap = Collections.emptyMap();
|
|
|
-
|
|
|
- private final SysConfigService sysConfigService;
|
|
|
-
|
|
|
- private final RedisService redisService;
|
|
|
-
|
|
|
- @Override
|
|
|
- public Optional<MultiQuantitySkuConfig> findConfig(Long skuId) {
|
|
|
- if (skuId == null || skuId <= 0) {
|
|
|
- return Optional.empty();
|
|
|
- }
|
|
|
- return Optional.ofNullable(loadConfigMap().get(skuId));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public boolean isMultiQuantity(Long skuId, Integer num) {
|
|
|
- return num != null && num > 1 && findConfig(skuId).isPresent();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public MultiQuantitySkuConfig validateAndGet(Long skuId, Integer num) {
|
|
|
- if (num == null || num <= 1) {
|
|
|
- throw BusinessRuntimeException.getInstance("多数量下单数量必须大于1");
|
|
|
- }
|
|
|
- MultiQuantitySkuConfig config = findConfig(skuId)
|
|
|
- .orElseThrow(() -> BusinessRuntimeException.getInstance("该规格不支持一次购买多个"));
|
|
|
- if (num > config.getMaxNum()) {
|
|
|
- throw BusinessRuntimeException.getInstance("该规格单次最多购买{0}个", config.getMaxNum());
|
|
|
- }
|
|
|
- return config;
|
|
|
- }
|
|
|
-
|
|
|
- private Map<Long, MultiQuantitySkuConfig> loadConfigMap() {
|
|
|
- SysConfig sysConfig = getSysConfig();
|
|
|
- if (sysConfig == null || StrUtil.isBlank(sysConfig.getSysValue())) {
|
|
|
- return Collections.emptyMap();
|
|
|
- }
|
|
|
- String configValue = sysConfig.getSysValue();
|
|
|
- if (configValue.equals(cachedConfigValue)) {
|
|
|
- return cachedConfigMap;
|
|
|
- }
|
|
|
- synchronized (this) {
|
|
|
- if (configValue.equals(cachedConfigValue)) {
|
|
|
- return cachedConfigMap;
|
|
|
- }
|
|
|
- Map<Long, MultiQuantitySkuConfig> parsedConfig = parseConfig(configValue);
|
|
|
- cachedConfigMap = parsedConfig;
|
|
|
- cachedConfigValue = configValue;
|
|
|
- return parsedConfig;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private Map<Long, MultiQuantitySkuConfig> parseConfig(String configValue) {
|
|
|
- try {
|
|
|
- List<MultiQuantitySkuConfig> configs = Jsons.parseList(configValue, MultiQuantitySkuConfig.class);
|
|
|
- if (CollUtil.isEmpty(configs)) {
|
|
|
- return Collections.emptyMap();
|
|
|
- }
|
|
|
- Map<Long, MultiQuantitySkuConfig> configMap = new HashMap<>(configs.size());
|
|
|
- for (MultiQuantitySkuConfig config : configs) {
|
|
|
- validateConfigEntry(config);
|
|
|
- if (configMap.put(config.getSkuId(), config) != null) {
|
|
|
- throw new IllegalArgumentException("duplicate skuId: " + config.getSkuId());
|
|
|
- }
|
|
|
- }
|
|
|
- return Collections.unmodifiableMap(configMap);
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("Invalid multi-quantity SKU config", e);
|
|
|
- throw BusinessRuntimeException.getInstance("多数量规格配置异常,请联系客服");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private SysConfig getSysConfig() {
|
|
|
- String cacheKey = RedisService.key.SYS_CONFIG_CACHE_KEY.getName() + CONFIG_KEY;
|
|
|
- try {
|
|
|
- Object cached = redisService.get(cacheKey);
|
|
|
- if (cached instanceof SysConfig) {
|
|
|
- return (SysConfig) cached;
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- log.warn("Read multi-quantity config cache failed: {}", e.getMessage());
|
|
|
- }
|
|
|
-
|
|
|
- SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
|
|
|
- .eq(SysConfig::getSysKey, CONFIG_KEY)
|
|
|
- .last("limit 1"));
|
|
|
- if (sysConfig != null) {
|
|
|
- try {
|
|
|
- redisService.set(cacheKey, sysConfig, CONFIG_CACHE_SECONDS);
|
|
|
- } catch (Exception e) {
|
|
|
- log.warn("Write multi-quantity config cache failed: {}", e.getMessage());
|
|
|
- }
|
|
|
- }
|
|
|
- return sysConfig;
|
|
|
- }
|
|
|
-
|
|
|
- private void validateConfigEntry(MultiQuantitySkuConfig config) {
|
|
|
- if (config == null || config.getSkuId() == null || config.getSkuId() <= 0
|
|
|
- || config.getMaxNum() == null || config.getMaxNum() < 2
|
|
|
- || config.getMaxNum() > ABSOLUTE_MAX_NUM) {
|
|
|
- throw new IllegalArgumentException("skuId and maxNum must be valid");
|
|
|
- }
|
|
|
- }
|
|
|
-}
|