|
|
@@ -0,0 +1,644 @@
|
|
|
+package shop.alien.storeplatform.service.impl;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.ObjectUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+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.entity.store.vo.StoreInfoVo;
|
|
|
+import shop.alien.entity.store.vo.StoreMainInfoVo;
|
|
|
+import shop.alien.entity.store.vo.StoreMenuVo;
|
|
|
+import shop.alien.entity.store.vo.WebSocketVo;
|
|
|
+import shop.alien.mapper.*;
|
|
|
+import shop.alien.storeplatform.feign.AlienStoreFeign;
|
|
|
+import shop.alien.storeplatform.service.StoreManageService;
|
|
|
+import shop.alien.storeplatform.util.GaoDeMapApiUtil;
|
|
|
+import shop.alien.storeplatform.util.NearMeUtil;
|
|
|
+import shop.alien.util.common.constant.OrderStatusEnum;
|
|
|
+import shop.alien.util.map.DistanceUtil;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * web端商户店铺管理服务实现类
|
|
|
+ *
|
|
|
+ * @author ssk
|
|
|
+ * @since 2025-01-xx
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class StoreManageServiceImpl implements StoreManageService {
|
|
|
+
|
|
|
+ private final StoreInfoMapper storeInfoMapper;
|
|
|
+
|
|
|
+ private final StoreDictionaryMapper storeDictionaryMapper;
|
|
|
+
|
|
|
+ private final EssentialCityCodeMapper essentialCityCodeMapper;
|
|
|
+
|
|
|
+ private final StoreUserMapper storeUserMapper;
|
|
|
+
|
|
|
+ private final StoreImgMapper storeImgMapper;
|
|
|
+
|
|
|
+ private final TagStoreRelationMapper tagStoreRelationMapper;
|
|
|
+
|
|
|
+ private final LifeNoticeMapper lifeNoticeMapper;
|
|
|
+
|
|
|
+ private final StoreInfoDraftMapper storeInfoDraftMapper;
|
|
|
+
|
|
|
+ private final StoreLabelMapper storeLabelMapper;
|
|
|
+
|
|
|
+ private final StoreBusinessInfoMapper storeBusinessInfoMapper;
|
|
|
+
|
|
|
+ private final StoreMenuMapper storeMenuMapper;
|
|
|
+
|
|
|
+ private final StoreIncomeDetailsRecordMapper storeIncomeDetailsRecordMapper;
|
|
|
+
|
|
|
+ private final LifeUserOrderMapper lifeUserOrderMapper;
|
|
|
+
|
|
|
+ private final NearMeUtil nearMeUtil;
|
|
|
+
|
|
|
+ private final AlienStoreFeign alienStoreFeign;
|
|
|
+
|
|
|
+ private final GaoDeMapApiUtil gaoDeMapApiUtil;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 默认店铺密码
|
|
|
+ */
|
|
|
+ private static final String DEFAULT_PASSWORD = "123456";
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public StoreInfoVo applyStore(StoreInfoDto storeInfoDto) throws Exception {
|
|
|
+ log.info("StoreManageServiceImpl.applyStore?storeInfoDto={}", storeInfoDto);
|
|
|
+
|
|
|
+ // 1. 获取经营板块信息
|
|
|
+ Integer businessSection = storeInfoDto.getBusinessSection();
|
|
|
+ StoreDictionary businessSectionDict = storeDictionaryMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<StoreDictionary>()
|
|
|
+ .eq(StoreDictionary::getDictId, businessSection)
|
|
|
+ .eq(StoreDictionary::getTypeName, "business_section")
|
|
|
+ );
|
|
|
+ if (businessSectionDict == null) {
|
|
|
+ throw new IllegalArgumentException("经营板块不存在:" + businessSection);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 获取经营种类信息
|
|
|
+ List<String> businessTypes = storeInfoDto.getBusinessTypes();
|
|
|
+ List<String> businessTypeNames = new ArrayList<>();
|
|
|
+ for (String businessType : businessTypes) {
|
|
|
+ StoreDictionary typeDict = storeDictionaryMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<StoreDictionary>()
|
|
|
+ .eq(StoreDictionary::getDictId, businessType)
|
|
|
+ .eq(StoreDictionary::getParentId, businessSectionDict.getId())
|
|
|
+ );
|
|
|
+ if (typeDict != null) {
|
|
|
+ businessTypeNames.add(typeDict.getDictDetail());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 构建店铺信息对象
|
|
|
+ StoreInfo storeInfo = new StoreInfo();
|
|
|
+ BeanUtils.copyProperties(storeInfoDto, storeInfo);
|
|
|
+
|
|
|
+ // 4. 设置店铺状态
|
|
|
+ storeInfo.setStoreStatus(storeInfoDto.getStoreStatus());
|
|
|
+
|
|
|
+ // 5. 设置经纬度
|
|
|
+ storeInfo.setStorePosition(
|
|
|
+ storeInfoDto.getStorePositionLongitude() + "," + storeInfoDto.getStorePositionLatitude()
|
|
|
+ );
|
|
|
+
|
|
|
+ // 6. 设置店铺密码
|
|
|
+ if (StringUtils.isNotEmpty(storeInfoDto.getStorePass())
|
|
|
+ && !DEFAULT_PASSWORD.equals(storeInfoDto.getStorePass())) {
|
|
|
+ storeInfo.setStorePass(storeInfoDto.getStorePass());
|
|
|
+ storeInfo.setPassType(1); // 已修改密码
|
|
|
+ } else {
|
|
|
+ storeInfo.setStorePass(DEFAULT_PASSWORD);
|
|
|
+ storeInfo.setPassType(0); // 初始密码
|
|
|
+ }
|
|
|
+
|
|
|
+ // 7. 设置经营板块及类型
|
|
|
+ storeInfo.setBusinessSection(businessSection);
|
|
|
+ storeInfo.setBusinessSectionName(businessSectionDict.getDictDetail());
|
|
|
+ storeInfo.setBusinessTypes(String.join(",", businessTypes));
|
|
|
+ storeInfo.setBusinessTypesName(String.join(",", businessTypeNames));
|
|
|
+
|
|
|
+ // 8. 设置审批状态为待审批
|
|
|
+ storeInfo.setStoreApplicationStatus(0);
|
|
|
+
|
|
|
+ // 9. 处理行政区域信息
|
|
|
+ setAdministrativeRegion(storeInfo);
|
|
|
+
|
|
|
+ // 10. 设置默认抽成比例
|
|
|
+ if (storeInfo.getCommissionRate() == null) {
|
|
|
+ storeInfo.setCommissionRate("3");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 11. 插入店铺信息
|
|
|
+ storeInfoMapper.insert(storeInfo);
|
|
|
+
|
|
|
+ // 12. 添加地理位置信息到Redis
|
|
|
+ try {
|
|
|
+ nearMeUtil.addGeolocation(
|
|
|
+ new Point(
|
|
|
+ Double.parseDouble(storeInfoDto.getStorePositionLongitude()),
|
|
|
+ Double.parseDouble(storeInfoDto.getStorePositionLatitude())
|
|
|
+ ),
|
|
|
+ storeInfo.getId().toString()
|
|
|
+ );
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("添加地理位置信息失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 13. 更新商户用户绑定关系
|
|
|
+ updateStoreUserBinding(storeInfoDto, storeInfo.getId());
|
|
|
+
|
|
|
+ // 14. 保存店铺图片信息
|
|
|
+ saveStoreImages(storeInfoDto, storeInfo.getId());
|
|
|
+
|
|
|
+ // 15. 初始化店铺标签
|
|
|
+ initializeStoreTags(storeInfo.getId());
|
|
|
+
|
|
|
+ // 16. 发送入住申请通知
|
|
|
+ sendApplicationNotice(storeInfoDto.getUserAccount());
|
|
|
+
|
|
|
+ // 17. 返回结果
|
|
|
+ StoreInfoVo result = new StoreInfoVo();
|
|
|
+ result.setId(storeInfo.getId());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置行政区域信息
|
|
|
+ */
|
|
|
+ private void setAdministrativeRegion(StoreInfo storeInfo) {
|
|
|
+ // 省
|
|
|
+ if (storeInfo.getAdministrativeRegionProvinceAdcode() != null) {
|
|
|
+ EssentialCityCode province = essentialCityCodeMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<EssentialCityCode>()
|
|
|
+ .eq(EssentialCityCode::getAreaCode, storeInfo.getAdministrativeRegionProvinceAdcode())
|
|
|
+ );
|
|
|
+ if (province != null) {
|
|
|
+ storeInfo.setAdministrativeRegionProvinceName(province.getAreaName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 市
|
|
|
+ if (storeInfo.getAdministrativeRegionCityAdcode() != null) {
|
|
|
+ EssentialCityCode city = essentialCityCodeMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<EssentialCityCode>()
|
|
|
+ .eq(EssentialCityCode::getAreaCode, storeInfo.getAdministrativeRegionCityAdcode())
|
|
|
+ );
|
|
|
+ if (city != null) {
|
|
|
+ storeInfo.setAdministrativeRegionCityName(city.getAreaName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 区/县
|
|
|
+ if (storeInfo.getAdministrativeRegionDistrictAdcode() != null) {
|
|
|
+ EssentialCityCode district = essentialCityCodeMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<EssentialCityCode>()
|
|
|
+ .eq(EssentialCityCode::getAreaCode, storeInfo.getAdministrativeRegionDistrictAdcode())
|
|
|
+ );
|
|
|
+ if (district != null) {
|
|
|
+ storeInfo.setAdministrativeRegionDistrictName(district.getAreaName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新商户用户绑定关系
|
|
|
+ */
|
|
|
+ private void updateStoreUserBinding(StoreInfoDto storeInfoDto, Integer storeId) {
|
|
|
+ String userAccount = storeInfoDto.getUserAccount();
|
|
|
+ StoreUser storeUser = storeUserMapper.selectById(userAccount);
|
|
|
+ if (storeUser != null) {
|
|
|
+ storeUser.setStoreId(storeId);
|
|
|
+
|
|
|
+ // 更新联系人信息
|
|
|
+ if (StringUtils.isNotEmpty(storeInfoDto.getStoreContact())) {
|
|
|
+ storeUser.setName(storeInfoDto.getStoreContact());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新身份证信息
|
|
|
+ if (StringUtils.isNotEmpty(storeInfoDto.getIdCard())) {
|
|
|
+ storeUser.setIdCard(storeInfoDto.getIdCard());
|
|
|
+ }
|
|
|
+
|
|
|
+ storeUserMapper.updateById(storeUser);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存店铺图片信息
|
|
|
+ */
|
|
|
+ private void saveStoreImages(StoreInfoDto storeInfoDto, Integer storeId) {
|
|
|
+ // 1. 保存营业执照图片 (imgType=14)
|
|
|
+ List<String> businessLicenseAddress = storeInfoDto.getBusinessLicenseAddress();
|
|
|
+ if (!CollectionUtils.isEmpty(businessLicenseAddress)) {
|
|
|
+ for (String licenseAddress : businessLicenseAddress) {
|
|
|
+ StoreImg storeImg = new StoreImg();
|
|
|
+ storeImg.setStoreId(storeId);
|
|
|
+ storeImg.setImgType(14);
|
|
|
+ storeImg.setImgSort(0);
|
|
|
+ storeImg.setImgDescription("营业执照");
|
|
|
+ storeImg.setImgUrl(licenseAddress);
|
|
|
+ storeImgMapper.insert(storeImg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 保存合同图片 (imgType=15)
|
|
|
+ List<String> contractImageList = storeInfoDto.getContractImageList();
|
|
|
+ if (!CollectionUtils.isEmpty(contractImageList)) {
|
|
|
+ // 先删除已存在的合同图片
|
|
|
+ storeImgMapper.delete(
|
|
|
+ new LambdaQueryWrapper<StoreImg>()
|
|
|
+ .eq(StoreImg::getStoreId, storeId)
|
|
|
+ .eq(StoreImg::getImgType, 15)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 插入新的合同图片
|
|
|
+ for (String contractImage : contractImageList) {
|
|
|
+ StoreImg storeImg = new StoreImg();
|
|
|
+ storeImg.setStoreId(storeId);
|
|
|
+ storeImg.setImgType(15);
|
|
|
+ storeImg.setImgSort(0);
|
|
|
+ storeImg.setImgDescription("合同图片");
|
|
|
+ storeImg.setImgUrl(contractImage);
|
|
|
+ storeImgMapper.insert(storeImg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 保存经营许可证图片 (imgType=25)
|
|
|
+ if (StringUtils.isNotEmpty(storeInfoDto.getFoodLicenceUrl())) {
|
|
|
+ StoreImg storeImg = new StoreImg();
|
|
|
+ storeImg.setStoreId(storeId);
|
|
|
+ storeImg.setImgType(25);
|
|
|
+ storeImg.setImgSort(0);
|
|
|
+ storeImg.setImgDescription("经营许可证审核通过图片");
|
|
|
+ storeImg.setImgUrl(storeInfoDto.getFoodLicenceUrl());
|
|
|
+ storeImgMapper.insert(storeImg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化店铺标签
|
|
|
+ */
|
|
|
+ private void initializeStoreTags(Integer storeId) {
|
|
|
+ // 检查是否已存在标签
|
|
|
+ LambdaQueryWrapper<TagStoreRelation> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(TagStoreRelation::getStoreId, storeId)
|
|
|
+ .eq(TagStoreRelation::getDeleteFlag, 0);
|
|
|
+ int tagCount = tagStoreRelationMapper.selectCount(wrapper);
|
|
|
+
|
|
|
+ // 如果不存在,创建初始标签
|
|
|
+ if (tagCount == 0) {
|
|
|
+ TagStoreRelation tagStoreRelation = new TagStoreRelation();
|
|
|
+ tagStoreRelation.setStoreId(storeId);
|
|
|
+ tagStoreRelation.setDeleteFlag(0);
|
|
|
+ tagStoreRelationMapper.insert(tagStoreRelation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送入住申请通知
|
|
|
+ */
|
|
|
+ private void sendApplicationNotice(String userAccount) {
|
|
|
+ try {
|
|
|
+ StoreUser storeUser = storeUserMapper.selectById(userAccount);
|
|
|
+ if (storeUser == null || StringUtils.isEmpty(storeUser.getPhone())) {
|
|
|
+ log.warn("未找到商户用户或手机号为空,无法发送通知");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+ String currentDate = sdf.format(new Date());
|
|
|
+ String message = "您在" + currentDate + "提交的入驻店铺申请,平台已受理,1-3个工作日将审核结果发送至应用内的消息-通知中,请注意查收。";
|
|
|
+
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ jsonObject.put("message", message);
|
|
|
+
|
|
|
+ String receiverId = "store_" + storeUser.getPhone();
|
|
|
+
|
|
|
+ // 1. 保存通知消息到数据库
|
|
|
+ LifeNotice lifeNotice = new LifeNotice();
|
|
|
+ lifeNotice.setReceiverId(receiverId);
|
|
|
+ lifeNotice.setContext(jsonObject.toJSONString());
|
|
|
+ lifeNotice.setTitle("入住店铺申请");
|
|
|
+ lifeNotice.setSenderId("system");
|
|
|
+ lifeNotice.setIsRead(0);
|
|
|
+ lifeNotice.setNoticeType(1);
|
|
|
+ lifeNoticeMapper.insert(lifeNotice);
|
|
|
+
|
|
|
+ // 2. 通过 WebSocket 实时推送消息
|
|
|
+ WebSocketVo websocketVo = new WebSocketVo();
|
|
|
+ websocketVo.setSenderId("system");
|
|
|
+ websocketVo.setReceiverId(receiverId);
|
|
|
+ websocketVo.setCategory("notice");
|
|
|
+ websocketVo.setNoticeType("1");
|
|
|
+ websocketVo.setIsRead(0);
|
|
|
+ websocketVo.setText(JSONObject.toJSONString(lifeNotice));
|
|
|
+
|
|
|
+ try {
|
|
|
+ alienStoreFeign.sendMsgToClientByPhoneId(receiverId, JSONObject.toJSONString(websocketVo));
|
|
|
+ log.info("WebSocket消息推送成功: receiverId={}", receiverId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("WebSocket消息推送失败: {}", e.getMessage(), e);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("发送入住申请通知失败: {}", e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int saveStoreDraft(StoreInfoDraft storeInfoDraft) {
|
|
|
+ log.info("StoreManageServiceImpl.saveStoreDraft - 开始保存店铺草稿");
|
|
|
+
|
|
|
+ // 处理行政区域省信息
|
|
|
+ if (storeInfoDraft.getAdministrativeRegionProvinceAdcode() != null) {
|
|
|
+ EssentialCityCode provinceCode = essentialCityCodeMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<EssentialCityCode>()
|
|
|
+ .eq(EssentialCityCode::getAreaCode, storeInfoDraft.getAdministrativeRegionProvinceAdcode())
|
|
|
+ );
|
|
|
+ if (provinceCode != null) {
|
|
|
+ storeInfoDraft.setAdministrativeRegionProvinceName(provinceCode.getAreaName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理行政区域市信息
|
|
|
+ if (storeInfoDraft.getAdministrativeRegionCityAdcode() != null) {
|
|
|
+ EssentialCityCode cityCode = essentialCityCodeMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<EssentialCityCode>()
|
|
|
+ .eq(EssentialCityCode::getAreaCode, storeInfoDraft.getAdministrativeRegionCityAdcode())
|
|
|
+ );
|
|
|
+ if (cityCode != null) {
|
|
|
+ storeInfoDraft.setAdministrativeRegionCityName(cityCode.getAreaName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理行政区域区信息
|
|
|
+ if (storeInfoDraft.getAdministrativeRegionDistrictAdcode() != null) {
|
|
|
+ EssentialCityCode districtCode = essentialCityCodeMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<EssentialCityCode>()
|
|
|
+ .eq(EssentialCityCode::getAreaCode, storeInfoDraft.getAdministrativeRegionDistrictAdcode())
|
|
|
+ );
|
|
|
+ if (districtCode != null) {
|
|
|
+ storeInfoDraft.setAdministrativeRegionDistrictName(districtCode.getAreaName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理空集合字段,设置为 null
|
|
|
+ if (StringUtils.isNotEmpty(storeInfoDraft.getBusinessLicenseUrl())
|
|
|
+ && storeInfoDraft.getBusinessLicenseUrl().isEmpty()) {
|
|
|
+ storeInfoDraft.setBusinessLicenseUrl(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(storeInfoDraft.getContractUrl())
|
|
|
+ && storeInfoDraft.getContractUrl().isEmpty()) {
|
|
|
+ storeInfoDraft.setContractUrl(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(storeInfoDraft.getFoodLicenceUrl())
|
|
|
+ && storeInfoDraft.getFoodLicenceUrl().isEmpty()) {
|
|
|
+ storeInfoDraft.setFoodLicenceUrl(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ int result = storeInfoDraftMapper.insert(storeInfoDraft);
|
|
|
+ log.info("StoreManageServiceImpl.saveStoreDraft - 草稿保存完成,影响行数: {}", result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public StoreInfoDraft getStoreDraft(int storeUserId) {
|
|
|
+ log.info("StoreManageServiceImpl.getStoreDraft - 查询商户用户草稿: storeUserId={}", storeUserId);
|
|
|
+
|
|
|
+ LambdaQueryWrapper<StoreInfoDraft> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(StoreInfoDraft::getStoreUserId, storeUserId);
|
|
|
+ wrapper.orderByDesc(StoreInfoDraft::getCreatedTime);
|
|
|
+
|
|
|
+ List<StoreInfoDraft> draftList = storeInfoDraftMapper.selectList(wrapper);
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(draftList)) {
|
|
|
+ log.info("StoreManageServiceImpl.getStoreDraft - 未找到草稿记录");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ StoreInfoDraft result = draftList.get(0);
|
|
|
+ log.info("StoreManageServiceImpl.getStoreDraft - 查询到草稿记录: id={}", result.getId());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public StoreMainInfoVo getStoreDetail(Integer id) {
|
|
|
+ log.info("StoreManageServiceImpl.getStoreDetail - 查询店铺详细信息: id={}", id);
|
|
|
+
|
|
|
+ // 1. 检查店铺是否存在
|
|
|
+ StoreInfo storeInfo = storeInfoMapper.selectById(id);
|
|
|
+ if (storeInfo == null) {
|
|
|
+ log.warn("StoreManageServiceImpl.getStoreDetail - 店铺不存在: id={}", id);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 获取店铺基本信息
|
|
|
+ StoreMainInfoVo storeMainInfoVo = storeInfoMapper.getStoreInfo(id);
|
|
|
+
|
|
|
+ // 3. 判断门店是否到期
|
|
|
+ if (ObjectUtils.isNotEmpty(storeMainInfoVo.getExpirationTime())) {
|
|
|
+ if (new Date().after(storeMainInfoVo.getExpirationTime())) {
|
|
|
+ storeMainInfoVo.setExpirationFlag(0); // 已到期
|
|
|
+ } else {
|
|
|
+ storeMainInfoVo.setExpirationFlag(1); // 未到期
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ storeMainInfoVo.setExpirationFlag(1); // 无到期时间,默认未到期
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 设置门店地址
|
|
|
+ storeMainInfoVo.setStoreAddress(storeInfo.getStoreAddress());
|
|
|
+
|
|
|
+ // 5. 查询入口图(imgType=1)
|
|
|
+ List<StoreImg> inletsUrlList = storeImgMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<StoreImg>()
|
|
|
+ .eq(StoreImg::getImgType, 1)
|
|
|
+ .eq(StoreImg::getStoreId, id)
|
|
|
+ );
|
|
|
+ List<String> inletsUrls = inletsUrlList.stream()
|
|
|
+ .sorted(Comparator.comparing(StoreImg::getImgSort))
|
|
|
+ .map(StoreImg::getImgUrl)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ storeMainInfoVo.setInletsUrl(inletsUrls);
|
|
|
+
|
|
|
+ // 6. 查询相册(imgType=2)
|
|
|
+ List<StoreImg> albumUrlList = storeImgMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<StoreImg>()
|
|
|
+ .eq(StoreImg::getImgType, 2)
|
|
|
+ .eq(StoreImg::getStoreId, id)
|
|
|
+ );
|
|
|
+ List<String> albumUrls = albumUrlList.stream()
|
|
|
+ .sorted(Comparator.comparing(StoreImg::getImgSort))
|
|
|
+ .map(StoreImg::getImgUrl)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ storeMainInfoVo.setAlbumUrl(albumUrls);
|
|
|
+
|
|
|
+ // 7. 查询推荐菜(isRecommend=1)
|
|
|
+ List<StoreMenuVo> recommendList = storeMenuMapper.getStoreMenuList(id, 1);
|
|
|
+ List<StoreMenuVo> sortedRecommendList = recommendList.stream()
|
|
|
+ .sorted(Comparator.comparing(StoreMenuVo::getImgSort))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ storeMainInfoVo.setRecommendUrl(sortedRecommendList);
|
|
|
+
|
|
|
+ // 8. 查询菜单(isRecommend=0)
|
|
|
+ List<StoreMenuVo> menuList = storeMenuMapper.getStoreMenuList(id, 0);
|
|
|
+ List<StoreMenuVo> sortedMenuList = menuList.stream()
|
|
|
+ .sorted(Comparator.comparing(StoreMenuVo::getImgSort))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ storeMainInfoVo.setMenuUrl(sortedMenuList);
|
|
|
+
|
|
|
+ // 9. 查询门店标签
|
|
|
+ StoreLabel storeLabel = storeLabelMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<StoreLabel>()
|
|
|
+ .eq(StoreLabel::getStoreId, id)
|
|
|
+ );
|
|
|
+ storeMainInfoVo.setStoreLabel(storeLabel);
|
|
|
+
|
|
|
+ // 10. 查询营业时间
|
|
|
+ List<StoreBusinessInfo> businessInfoList = storeBusinessInfoMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<StoreBusinessInfo>()
|
|
|
+ .eq(StoreBusinessInfo::getStoreId, id)
|
|
|
+ );
|
|
|
+ storeMainInfoVo.setStoreBusinessInfo(businessInfoList);
|
|
|
+
|
|
|
+ // 11. 查询门店头像(imgType=10)
|
|
|
+ StoreImg headImg = storeImgMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<StoreImg>()
|
|
|
+ .eq(StoreImg::getImgType, 10)
|
|
|
+ .eq(StoreImg::getStoreId, id)
|
|
|
+ );
|
|
|
+ storeMainInfoVo.setHeadImgUrl(headImg != null ? headImg.getImgUrl() : "");
|
|
|
+
|
|
|
+ // 12. 查询商户用户注销状态
|
|
|
+ List<StoreUser> storeUsers = storeUserMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<StoreUser>()
|
|
|
+ .eq(StoreUser::getStoreId, storeInfo.getId())
|
|
|
+ );
|
|
|
+ for (StoreUser storeUser : storeUsers) {
|
|
|
+ storeMainInfoVo.setLogoutFlagUser(storeUser.getLogoutFlag());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 13. 计算店铺到最近地铁站的距离
|
|
|
+ try {
|
|
|
+ String[] position = storeMainInfoVo.getStorePosition().split(",");
|
|
|
+ if (position.length == 2) {
|
|
|
+ String longitude = position[0];
|
|
|
+ String latitude = position[1];
|
|
|
+
|
|
|
+ JSONObject nearbySubway = gaoDeMapApiUtil.getNearbySubway(longitude, latitude);
|
|
|
+
|
|
|
+ // 地铁站名称
|
|
|
+ String subwayName = nearbySubway.getString("name");
|
|
|
+ storeMainInfoVo.setSubwayName(subwayName);
|
|
|
+
|
|
|
+ // 地铁站经纬度
|
|
|
+ String location = nearbySubway.getString("location");
|
|
|
+ if (StringUtils.isNotEmpty(location)) {
|
|
|
+ String[] subwayPosition = location.split(",");
|
|
|
+ if (subwayPosition.length == 2) {
|
|
|
+ double subwayLng = Double.parseDouble(subwayPosition[0]);
|
|
|
+ double subwayLat = Double.parseDouble(subwayPosition[1]);
|
|
|
+ double storeLng = Double.parseDouble(longitude);
|
|
|
+ double storeLat = Double.parseDouble(latitude);
|
|
|
+
|
|
|
+ // 计算距离(米)
|
|
|
+ double distance = DistanceUtil.haversineCalculateDistance(
|
|
|
+ subwayLng, subwayLat, storeLng, storeLat);
|
|
|
+ storeMainInfoVo.setDistance2(distance);
|
|
|
+ } else {
|
|
|
+ storeMainInfoVo.setDistance2(0);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ storeMainInfoVo.setDistance2(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("StoreManageServiceImpl.getStoreDetail - 计算地铁距离失败: {}", e.getMessage(), e);
|
|
|
+ storeMainInfoVo.setSubwayName("");
|
|
|
+ storeMainInfoVo.setDistance2(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("StoreManageServiceImpl.getStoreDetail - 查询完成: id={}", id);
|
|
|
+ return storeMainInfoVo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getTodayIncome(Integer storeId) {
|
|
|
+ log.info("StoreManageServiceImpl.getTodayIncome - 查询店铺今日收益: storeId={}", storeId);
|
|
|
+
|
|
|
+ // 1. 构建查询条件
|
|
|
+ LambdaQueryWrapper<StoreIncomeDetailsRecord> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
+
|
|
|
+ // 2. 查询今日的收入记录
|
|
|
+ wrapper.eq(StoreIncomeDetailsRecord::getStoreId, storeId)
|
|
|
+ .ge(StoreIncomeDetailsRecord::getCreatedTime, today + " 00:00:00")
|
|
|
+ .le(StoreIncomeDetailsRecord::getCreatedTime, today + " 23:59:59");
|
|
|
+
|
|
|
+ List<StoreIncomeDetailsRecord> incomeList = storeIncomeDetailsRecordMapper.selectList(wrapper);
|
|
|
+
|
|
|
+ // 3. 计算总收益(单位:分)
|
|
|
+ int totalIncome = 0;
|
|
|
+ if (incomeList != null && !incomeList.isEmpty()) {
|
|
|
+ totalIncome = incomeList.stream()
|
|
|
+ .mapToInt(StoreIncomeDetailsRecord::getMoney)
|
|
|
+ .sum();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 转换为元,保留两位小数
|
|
|
+ String incomeStr = new BigDecimal(totalIncome)
|
|
|
+ .divide(new BigDecimal(100), 2, RoundingMode.DOWN)
|
|
|
+ .toString();
|
|
|
+
|
|
|
+ log.info("StoreManageServiceImpl.getTodayIncome - 查询完成: storeId={}, 今日收益={}元",
|
|
|
+ storeId, incomeStr);
|
|
|
+ return incomeStr;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer getTodayOrderCount(Integer storeId) {
|
|
|
+ log.info("StoreManageServiceImpl.getTodayOrderCount - 查询店铺今日订单数: storeId={}", storeId);
|
|
|
+
|
|
|
+ // 1. 构建查询条件
|
|
|
+ LambdaQueryWrapper<LifeUserOrder> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
+
|
|
|
+ // 2. 查询今日的订单,排除待支付、已取消、已过期状态
|
|
|
+ wrapper.eq(LifeUserOrder::getStoreId, storeId)
|
|
|
+ .notIn(LifeUserOrder::getStatus,
|
|
|
+ OrderStatusEnum.CANCEL.getStatus(),
|
|
|
+ OrderStatusEnum.WAIT_PAY.getStatus(),
|
|
|
+ OrderStatusEnum.EXPIRE.getStatus())
|
|
|
+ .between(LifeUserOrder::getBuyTime, today + " 00:00:00", today + " 23:59:59");
|
|
|
+
|
|
|
+ // 3. 统计订单数量
|
|
|
+ Integer count = lifeUserOrderMapper.selectCount(wrapper);
|
|
|
+
|
|
|
+ log.info("StoreManageServiceImpl.getTodayOrderCount - 查询完成: storeId={}, 今日订单数={}",
|
|
|
+ storeId, count);
|
|
|
+ return count;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|