|
@@ -0,0 +1,196 @@
|
|
|
|
|
+package shop.alien.storeplatform.service.impl;
|
|
|
|
|
+
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
|
|
+import org.springframework.data.geo.Point;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
|
|
+import shop.alien.entity.store.*;
|
|
|
|
|
+import shop.alien.entity.store.dto.StoreInfoDto;
|
|
|
|
|
+import shop.alien.mapper.*;
|
|
|
|
|
+import shop.alien.storeplatform.service.NearMeService;
|
|
|
|
|
+import shop.alien.storeplatform.service.StorePlatformInfoService;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+import java.util.Objects;
|
|
|
|
|
+import java.util.function.Function;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
+
|
|
|
|
|
+@Service
|
|
|
|
|
+@RequiredArgsConstructor
|
|
|
|
|
+@Transactional
|
|
|
|
|
+public class StorePlatformInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo> implements StorePlatformInfoService {
|
|
|
|
|
+
|
|
|
|
|
+ private final LifeUserOrderMapper lifeUserOrderMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private final LifeGroupBuyMainMapper lifeGroupBuyMainMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private final LifeCouponMapper lifeCouponMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private final StoreDictionaryMapper storeDictionaryMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private final StoreInfoMapper storeInfoMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private final EssentialCityCodeMapper essentialCityCodeMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private final NearMeService nearMeService;
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int saveOrUpdateStoreInfo(StoreInfoDto storeInfodto) {
|
|
|
|
|
+ if (storeInfodto.getId() != null) {
|
|
|
|
|
+ // 校验当前店铺存在未完成的订单及正在销售的商品
|
|
|
|
|
+ verificationStoreInfoStatus(storeInfodto);
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 处理经营板块及经营种类
|
|
|
|
|
+ Integer businessSection = storeInfodto.getBusinessSection();
|
|
|
|
|
+ StoreDictionary businessSectionDict = null;
|
|
|
|
|
+ List<String> businessTypeNames = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+ // 查询经营板块(非空判断,避免后续空指针)
|
|
|
|
|
+ if (Objects.nonNull(businessSection)) {
|
|
|
|
|
+ businessSectionDict = storeDictionaryMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<StoreDictionary>()
|
|
|
|
|
+ .eq(StoreDictionary::getDictId, businessSection)
|
|
|
|
|
+ .eq(StoreDictionary::getTypeName, "business_section")
|
|
|
|
|
+ );
|
|
|
|
|
+ // 若经营板块不存在,可根据业务抛出异常或默认处理
|
|
|
|
|
+ if (Objects.isNull(businessSectionDict)) {
|
|
|
|
|
+ throw new IllegalArgumentException("经营板块不存在:" + businessSection);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 批量查询经营种类(替代循环查询,解决N+1问题)
|
|
|
|
|
+ List<String> businessTypes = storeInfodto.getBusinessTypes();
|
|
|
|
|
+ if (Objects.nonNull(businessSectionDict) && !CollectionUtils.isEmpty(businessTypes)) {
|
|
|
|
|
+ // 一次查询所有符合条件的经营种类
|
|
|
|
|
+ List<StoreDictionary> typeDicts = storeDictionaryMapper.selectList(
|
|
|
|
|
+ new LambdaQueryWrapper<StoreDictionary>()
|
|
|
|
|
+ .in(StoreDictionary::getDictId, businessTypes) // 批量匹配id
|
|
|
|
|
+ .eq(StoreDictionary::getParentId, businessSectionDict.getId())
|
|
|
|
|
+ );
|
|
|
|
|
+ // 转为Map<dictId, StoreDictionary>,方便快速获取
|
|
|
|
|
+ Map<String, StoreDictionary> typeDictMap = typeDicts.stream()
|
|
|
|
|
+ .collect(Collectors.toMap(
|
|
|
|
|
+ dict -> dict.getDictId().toString(), // 假设dictId是字符串类型,若为数字需转换
|
|
|
|
|
+ Function.identity(),
|
|
|
|
|
+ (existing, replacement) -> existing // 处理重复id(理论上不会有)
|
|
|
|
|
+ ));
|
|
|
|
|
+ // 提取经营种类名称
|
|
|
|
|
+ for (String typeId : businessTypes) {
|
|
|
|
|
+ StoreDictionary dict = typeDictMap.get(typeId);
|
|
|
|
|
+ if (Objects.nonNull(dict)) {
|
|
|
|
|
+ businessTypeNames.add(dict.getDictDetail());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 可选:记录无效的经营种类id,便于排查
|
|
|
|
|
+ log.warn("无效的经营种类id:" + typeId + "(所属板块:" + businessSectionDict.getDictDetail() + ")");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 构建StoreInfo对象
|
|
|
|
|
+ StoreInfo storeInfo = new StoreInfo();
|
|
|
|
|
+ BeanUtils.copyProperties(storeInfodto, storeInfo);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 处理经纬度
|
|
|
|
|
+ String longitude = storeInfodto.getStorePositionLongitude();
|
|
|
|
|
+ String latitude = storeInfodto.getStorePositionLatitude();
|
|
|
|
|
+ if (StringUtils.isEmpty(longitude) || StringUtils.isEmpty(latitude)) {
|
|
|
|
|
+ // 经纬度为空时,复用原数据
|
|
|
|
|
+ StoreInfo oldStore = storeInfoMapper.selectById(storeInfodto.getId());
|
|
|
|
|
+ if (Objects.nonNull(oldStore)) {
|
|
|
|
|
+ storeInfo.setStorePosition(oldStore.getStorePosition());
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 拼接经纬度
|
|
|
|
|
+ storeInfo.setStorePosition(longitude + "," + latitude);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 设置门店状态、经营板块及类型
|
|
|
|
|
+ storeInfo.setStoreStatus(storeInfodto.getStoreStatus());
|
|
|
|
|
+ // 经营板块(非空时才设置)
|
|
|
|
|
+ if (Objects.nonNull(businessSection)) {
|
|
|
|
|
+ storeInfo.setBusinessSection(businessSection);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 经营板块名称(非空时才设置)
|
|
|
|
|
+ if (Objects.nonNull(businessSectionDict)) {
|
|
|
|
|
+ storeInfo.setBusinessSectionName(businessSectionDict.getDictDetail());
|
|
|
|
|
+ }
|
|
|
|
|
+ // 经营种类及名称(非空时拼接)
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(businessTypes) && !CollectionUtils.isEmpty(businessTypeNames)) {
|
|
|
|
|
+ storeInfo.setBusinessTypes(String.join(",", businessTypes));
|
|
|
|
|
+ storeInfo.setBusinessTypesName(String.join(",", businessTypeNames));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 处理行政区域信息(抽取为方法,减少重复) 不存在单独查的情况
|
|
|
|
|
+ if (!Objects.isNull(storeInfo.getAdministrativeRegionProvinceAdcode())) {
|
|
|
|
|
+
|
|
|
|
|
+ storeInfo.setAdministrativeRegionProvinceName(
|
|
|
|
|
+ getAreaName(storeInfo.getAdministrativeRegionProvinceAdcode())
|
|
|
|
|
+ );
|
|
|
|
|
+ storeInfo.setAdministrativeRegionCityName(
|
|
|
|
|
+ getAreaName(storeInfo.getAdministrativeRegionCityAdcode())
|
|
|
|
|
+ );
|
|
|
|
|
+ storeInfo.setAdministrativeRegionDistrictName(
|
|
|
|
|
+ getAreaName(storeInfo.getAdministrativeRegionDistrictAdcode())
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 执行更新
|
|
|
|
|
+ int updateNum = storeInfoMapper.updateById(storeInfo);
|
|
|
|
|
+
|
|
|
|
|
+ // 7. 更新地理位置信息(处理经纬度解析异常)
|
|
|
|
|
+ if (!StringUtils.isEmpty(longitude) && !StringUtils.isEmpty(latitude)) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ double lon = Double.parseDouble(longitude);
|
|
|
|
|
+ double lat = Double.parseDouble(latitude);
|
|
|
|
|
+ nearMeService.inGeolocation(new Point(lon, lat), storeInfo.getId().toString(), Boolean.TRUE);
|
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
|
+ log.error("经纬度解析失败:longitude=" + longitude + ", latitude=" + latitude);
|
|
|
|
|
+ // 可选:根据业务是否抛出异常,或忽略
|
|
|
|
|
+ // throw new IllegalArgumentException("经纬度格式错误", e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return updateNum;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ StoreInfo storeInfo = new StoreInfo();
|
|
|
|
|
+ BeanUtils.copyProperties(storeInfodto, storeInfo);
|
|
|
|
|
+ int num = storeInfoMapper.insert(storeInfo);
|
|
|
|
|
+ return num;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void verificationStoreInfoStatus(StoreInfoDto storeInfo) {
|
|
|
|
|
+ //营业状态 0:正常营业, 1:暂停营业, 2:筹建中, 99:永久关门
|
|
|
|
|
+ if (storeInfo.getBusinessStatus() == 99) {
|
|
|
|
|
+ //判断店铺有未完成的订单
|
|
|
|
|
+ List<LifeUserOrder> lifeUserOrders = lifeUserOrderMapper.selectList(new LambdaQueryWrapper<LifeUserOrder>().in(LifeUserOrder::getStatus, 0, 3).eq(LifeUserOrder::getStoreId, storeInfo.getId()).eq(LifeUserOrder::getDeleteFlag, 0));
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(lifeUserOrders)) {
|
|
|
|
|
+ throw new RuntimeException("店铺有未完成的订单");
|
|
|
|
|
+ }
|
|
|
|
|
+ //判断店铺有正在售卖的商品
|
|
|
|
|
+ List<LifeGroupBuyMain> lifeGroupBuyMainList = lifeGroupBuyMainMapper.selectList(new LambdaQueryWrapper<LifeGroupBuyMain>().eq(LifeGroupBuyMain::getStoreId, storeInfo.getId()).eq(LifeGroupBuyMain::getStatus, 5).eq(LifeGroupBuyMain::getDeleteFlag, 0));
|
|
|
|
|
+ List<LifeCoupon> lifeCoupons = lifeCouponMapper.selectList(new LambdaQueryWrapper<LifeCoupon>().in(LifeCoupon::getStatus, 0, 1).and(qw -> qw.gt(LifeCoupon::getStockQty, 0).or().gt(LifeCoupon::getSingleQty, 0)).eq(LifeCoupon::getStoreId, storeInfo.getId()).eq(LifeCoupon::getType, 1).eq(LifeCoupon::getDeleteFlag, 0));
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(lifeCoupons) || !CollectionUtils.isEmpty(lifeGroupBuyMainList)) {
|
|
|
|
|
+ throw new RuntimeException("店铺有正在销售的商品");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 抽取:根据区域编码查询区域名称(通用方法)
|
|
|
|
|
+ private String getAreaName(String areaCode) {
|
|
|
|
|
+ if (StringUtils.isEmpty(areaCode)) {
|
|
|
|
|
+ return ""; // 或返回null,根据业务定义
|
|
|
|
|
+ }
|
|
|
|
|
+ EssentialCityCode cityCode = essentialCityCodeMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, areaCode)
|
|
|
|
|
+ );
|
|
|
|
|
+ return Objects.nonNull(cityCode) ? cityCode.getAreaName() : "";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|