| | |
| | | package com.doumee.service.business.impl; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.doumee.config.jwt.JwtTokenUtil; |
| | | import com.doumee.core.constants.Constants; |
| | | import com.doumee.core.constants.ResponseStatus; |
| | | import com.doumee.core.exception.BusinessException; |
| | |
| | | import com.doumee.biz.system.SystemDictDataBiz; |
| | | import com.doumee.dao.business.MemberMapper; |
| | | import com.doumee.dao.business.MultifileMapper; |
| | | import com.doumee.dao.business.OrdersMapper; |
| | | import com.doumee.dao.business.PricingRuleMapper; |
| | | import com.doumee.dao.business.ShopInfoMapper; |
| | | import com.doumee.dao.business.model.Areas; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.business.model.Multifile; |
| | | import com.doumee.dao.business.model.Orders; |
| | | import com.doumee.dao.business.model.PricingRule; |
| | | import com.doumee.dao.business.model.ShopInfo; |
| | | import com.doumee.dao.dto.AuditDTO; |
| | | import com.doumee.dao.dto.ChangeStatusDTO; |
| | | import com.doumee.dao.dto.ResetPasswordDTO; |
| | | import com.doumee.dao.dto.ShopApplyDTO; |
| | | import com.doumee.dao.dto.ShopUpdateDTO; |
| | | import com.doumee.dao.dto.*; |
| | | import com.doumee.dao.system.SystemUserMapper; |
| | | import com.doumee.dao.system.model.SystemUser; |
| | | import com.doumee.dao.vo.ShopDetailVO; |
| | | import com.doumee.dao.vo.ShopCenterVO; |
| | | import com.doumee.dao.vo.ShopLoginVO; |
| | | import com.doumee.dao.vo.ShopNearbyVO; |
| | | import com.doumee.dao.vo.ShopWebDetailVO; |
| | | import com.doumee.service.business.AreasService; |
| | | import com.doumee.service.business.ShopInfoService; |
| | | import org.apache.commons.collections.CollectionUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.apache.commons.lang3.RandomStringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | |
| | | private SystemDictDataBiz systemDictDataBiz; |
| | | |
| | | @Autowired |
| | | private SystemUserMapper systemUserMapper; |
| | | |
| | | @Autowired |
| | | private AreasBiz areasBiz; |
| | | |
| | | @Autowired |
| | | private RedisTemplate<String,Object> redisTemplate; |
| | | |
| | | @Autowired |
| | | private PricingRuleMapper pricingRuleMapper; |
| | | |
| | | @Autowired |
| | | private OrdersMapper ordersMapper; |
| | | |
| | | @Autowired |
| | | private AreasService areasService; |
| | | @Override |
| | | public Integer create(ShopInfo shopInfo) { |
| | | shopInfoMapper.insert(shopInfo); |
| | |
| | | if (pageWrap.getModel().getAuditStatus() != null) { |
| | | queryWrapper.lambda().eq(ShopInfo::getAuditStatus, pageWrap.getModel().getAuditStatus()); |
| | | } |
| | | if (pageWrap.getModel().getAuditStatusList() != null && !pageWrap.getModel().getAuditStatusList().isEmpty()) { |
| | | queryWrapper.lambda().in(ShopInfo::getAuditStatus, pageWrap.getModel().getAuditStatusList()); |
| | | } |
| | | if (pageWrap.getModel().getStatus() != null) { |
| | | queryWrapper.lambda().eq(ShopInfo::getStatus, pageWrap.getModel().getStatus()); |
| | | } |
| | |
| | | existing.setLegalPersonCard(request.getLegalPersonCard()); |
| | | existing.setPassword(encryptedPassword); |
| | | existing.setSalt(salt); |
| | | existing.setAliAccount(request.getAliAccount()); |
| | | existing.setAuditStatus(Constants.ZERO); |
| | | existing.setUpdateTime(now); |
| | | existing.setUpdateUser(memberId); |
| | |
| | | shopInfo.setLegalPersonCard(request.getLegalPersonCard()); |
| | | shopInfo.setPassword(encryptedPassword); |
| | | shopInfo.setSalt(salt); |
| | | shopInfo.setAliAccount(request.getAliAccount()); |
| | | shopInfo.setOpenid(member.getOpenid()); |
| | | shopInfo.setAuditStatus(Constants.ZERO); |
| | | shopInfo.setStatus(Constants.ZERO); |
| | |
| | | shopInfo.setAuditRemark(auditDTO.getAuditRemark()); |
| | | shopInfo.setAuditUserId(auditDTO.getAuditUser()); |
| | | shopInfo.setUpdateTime(now); |
| | | // 审批通过时,校验城市pricing_rule配置,读取押金金额 |
| | | if (Constants.equalsInteger(newAuditStatus, Constants.ONE)) { |
| | | // 1. 解析门店所在城市 |
| | | Areas area = areasBiz.resolveArea(shopInfo.getAreaId()); |
| | | if (area == null || area.getParentId() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "门店区划信息异常,无法确定所在城市"); |
| | | } |
| | | Integer cityId = area.getParentId(); |
| | | |
| | | // 2. 校验 pricing_rule 配置(城市开通在押金支付完成后处理) |
| | | Areas cityArea = areasService.findById(cityId, Constants.ONE); |
| | | if (cityArea == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "城市信息不存在"); |
| | | } |
| | | if (!Constants.equalsInteger(cityArea.getStatus(), Constants.ONE)) { |
| | | List<String> errors = validateCityPricingRules(cityId); |
| | | if (!errors.isEmpty()) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), |
| | | "城市[" + cityArea.getName() + "]尚未开通,定价规则未配置完整:" + String.join(";", errors)); |
| | | } |
| | | } |
| | | |
| | | // 3. 从PricingRule读取押金金额 |
| | | PricingRule pricingRule = pricingRuleMapper.selectOne(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.THREE) |
| | | .eq(PricingRule::getFieldA, String.valueOf(shopInfo.getCompanyType())) |
| | | .last("limit 1")); |
| | | if (pricingRule != null && StringUtils.isNotBlank(pricingRule.getFieldB())) { |
| | | shopInfo.setDepositAmount(Long.parseLong(pricingRule.getFieldB())); |
| | | } |
| | | } |
| | | shopInfoMapper.updateById(shopInfo); |
| | | } |
| | | |
| | |
| | | vo.setAuditStatus(shopInfo.getAuditStatus()); |
| | | vo.setStatus(shopInfo.getStatus()); |
| | | vo.setAuditTime(shopInfo.getAuditTime()); |
| | | if(Objects.nonNull(shopInfo.getAuditUserId())){ |
| | | SystemUser systemUser = systemUserMapper.selectById(shopInfo.getAuditUserId()); |
| | | if (systemUser != null) vo.setAuditName(systemUser.getRealname()); |
| | | |
| | | } |
| | | vo.setAuditRemark(shopInfo.getAuditRemark()); |
| | | vo.setOpenid(shopInfo.getOpenid()); |
| | | vo.setPayStatus(shopInfo.getPayStatus()); |
| | |
| | | // 拼接图片前缀 |
| | | String imgPrefix = ""; |
| | | try { |
| | | imgPrefix = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.RESOURCE_PATH).getCode() |
| | | imgPrefix = systemDictDataBiz.queryByCode(Constants.OSS, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.SHOP_FILES).getCode(); |
| | | } catch (Exception e) { |
| | | // 未配置时忽略 |
| | | } |
| | | vo.setImgPrefix(imgPrefix); |
| | | |
| | | // 单图字段返回半路径 |
| | | // 单图字段:半路径 + 全路径 |
| | | vo.setIdcardImg(shopInfo.getIdcardImg()); |
| | | vo.setIdcardImgUrl(StringUtils.isNotBlank(shopInfo.getIdcardImg()) ? imgPrefix + shopInfo.getIdcardImg() : null); |
| | | vo.setIdcardImgBack(shopInfo.getIdcardImgBack()); |
| | | vo.setIdcardImgBackUrl(StringUtils.isNotBlank(shopInfo.getIdcardImgBack()) ? imgPrefix + shopInfo.getIdcardImgBack() : null); |
| | | vo.setBusinessImg(shopInfo.getBusinessImg()); |
| | | vo.setBusinessImgUrl(StringUtils.isNotBlank(shopInfo.getBusinessImg()) ? imgPrefix + shopInfo.getBusinessImg() : null); |
| | | |
| | | // 查询附件 |
| | | QueryWrapper<Multifile> fileQw = new QueryWrapper<>(); |
| | |
| | | .orderByAsc(Multifile::getObjType, Multifile::getSortnum); |
| | | List<Multifile> files = multifileMapper.selectList(fileQw); |
| | | |
| | | // 按 objType 分组,返回半路径 |
| | | // 按 objType 分组,半路径 + 全路径 |
| | | Map<Integer, List<String>> fileMap = new HashMap<>(); |
| | | Map<Integer, List<String>> fileUrlMap = new HashMap<>(); |
| | | for (Multifile f : files) { |
| | | fileMap.computeIfAbsent(f.getObjType(), k -> new ArrayList<>()).add(f.getFileurl()); |
| | | String fullUrl = StringUtils.isNotBlank(f.getFileurl()) ? imgPrefix + f.getFileurl() : f.getFileurl(); |
| | | fileUrlMap.computeIfAbsent(f.getObjType(), k -> new ArrayList<>()).add(fullUrl); |
| | | } |
| | | |
| | | vo.setStoreFrontImgs(fileMap.getOrDefault(Constants.FileType.STORE_FRONT.getKey(), new ArrayList<>())); |
| | |
| | | vo.setLaborContractImgs(fileMap.getOrDefault(Constants.FileType.LABOR_CONTRACT.getKey(), new ArrayList<>())); |
| | | vo.setSocialSecurityImgs(fileMap.getOrDefault(Constants.FileType.SOCIAL_SECURITY.getKey(), new ArrayList<>())); |
| | | |
| | | vo.setStoreFrontImgUrls(fileUrlMap.getOrDefault(Constants.FileType.STORE_FRONT.getKey(), new ArrayList<>())); |
| | | vo.setStoreInteriorImgUrls(fileUrlMap.getOrDefault(Constants.FileType.STORE_INTERIOR.getKey(), new ArrayList<>())); |
| | | vo.setOtherMaterialImgUrls(fileUrlMap.getOrDefault(Constants.FileType.OTHER_MATERIAL.getKey(), new ArrayList<>())); |
| | | vo.setLaborContractImgUrls(fileUrlMap.getOrDefault(Constants.FileType.LABOR_CONTRACT.getKey(), new ArrayList<>())); |
| | | vo.setSocialSecurityImgUrls(fileUrlMap.getOrDefault(Constants.FileType.SOCIAL_SECURITY.getKey(), new ArrayList<>())); |
| | | |
| | | // 查询绑定开户会员头像(payMemberOpenId 关联 member.openid) |
| | | if (StringUtils.isNotBlank(shopInfo.getPayMemberOpenId())) { |
| | | QueryWrapper<Member> memberQw = new QueryWrapper<>(); |
| | | memberQw.lambda().eq(Member::getOpenid, shopInfo.getPayMemberOpenId()).last("limit 1"); |
| | | Member payMember = memberMapper.selectOne(memberQw); |
| | | if (payMember != null) { |
| | | vo.setPayMemberCoverImage(payMember.getCoverImage()); |
| | | if (payMember != null && StringUtils.isNotBlank(payMember.getCoverImage())) { |
| | | String memberPrefix = ""; |
| | | try { |
| | | memberPrefix = systemDictDataBiz.queryByCode(Constants.OSS, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.MEMBER_FILES).getCode(); |
| | | } catch (Exception e) { |
| | | // 未配置时忽略 |
| | | } |
| | | vo.setPayMemberCoverImage(memberPrefix + payMember.getCoverImage()); |
| | | } |
| | | } |
| | | |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | public PageData<ShopNearbyVO> findNearbyShops(PageWrap<ShopNearbyDTO> pageWrap) { |
| | | IPage<ShopInfo> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | ShopNearbyDTO dto = pageWrap.getModel(); |
| | | Double longitude = dto.getLongitude(); |
| | | Double latitude = dto.getLatitude(); |
| | | Integer sortType = dto.getSortType(); |
| | | Integer distanceMeter = dto.getDistance(); |
| | | |
| | | // Haversine距离公式(单位km) |
| | | String distanceFormula = "(6371 * acos(cos(radians(" + latitude + ")) * cos(radians(latitude)) " + |
| | | "* cos(radians(longitude) - radians(" + longitude + ")) " + |
| | | "+ sin(radians(" + latitude + ")) * sin(radians(latitude))))"; |
| | | |
| | | QueryWrapper<ShopInfo> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .eq(ShopInfo::getStatus, Constants.ZERO) |
| | | .eq(ShopInfo::getAuditStatus, Constants.THREE); |
| | | |
| | | // 门店营业类型筛选 |
| | | if (dto.getBusinessType() != null) { |
| | | qw.lambda().eq(ShopInfo::getBusinessType, dto.getBusinessType()); |
| | | } |
| | | |
| | | // 门店名称模糊查询 |
| | | if (StringUtils.isNotBlank(dto.getName())) { |
| | | qw.lambda().like(ShopInfo::getName, dto.getName()); |
| | | } |
| | | |
| | | // 距离筛选(单位:米 → 转换为km比较) |
| | | if (distanceMeter != null && distanceMeter > 0) { |
| | | double maxKm = distanceMeter / 1000.0; |
| | | qw.apply(distanceFormula + " <= {0}", maxKm); |
| | | } |
| | | |
| | | // 排序 |
| | | if (longitude != null && latitude != null) { |
| | | if (sortType != null && sortType == 2) { |
| | | // 按评分降序 |
| | | qw.last("ORDER BY score DESC"); |
| | | } else { |
| | | // 默认:按距离升序 |
| | | qw.last("ORDER BY " + distanceFormula + " ASC"); |
| | | } |
| | | } else { |
| | | qw.lambda().orderByDesc(ShopInfo::getCreateTime); |
| | | } |
| | | |
| | | IPage<ShopInfo> result = shopInfoMapper.selectPage(page, qw); |
| | | |
| | | // 图片前缀 |
| | | String imgPrefix = getShopPrefix(); |
| | | |
| | | List<ShopNearbyVO> voList = new ArrayList<>(); |
| | | for (ShopInfo shop : result.getRecords()) { |
| | | ShopNearbyVO vo = new ShopNearbyVO(); |
| | | vo.setId(shop.getId()); |
| | | vo.setName(shop.getName()); |
| | | vo.setShopHours(shop.getShopHours()); |
| | | vo.setAddress(shop.getAddress()); |
| | | vo.setScore(shop.getScore()); |
| | | // 门头照第一张 |
| | | vo.setCoverImg(getFirstImage(shop.getId(), Constants.FileType.STORE_FRONT.getKey(), imgPrefix)); |
| | | // 距离 |
| | | if (longitude != null && latitude != null && shop.getLongitude() != null && shop.getLatitude() != null) { |
| | | double distKm = haversine(latitude, longitude, shop.getLatitude(), shop.getLongitude()); |
| | | vo.setDistanceText(formatDistance(distKm)); |
| | | } |
| | | voList.add(vo); |
| | | } |
| | | IPage<ShopNearbyVO> vPage = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | PageData<ShopNearbyVO> pageData = PageData.from(vPage); |
| | | pageData.setRecords(voList); |
| | | pageData.setTotal(result.getTotal()); |
| | | pageData.setPage(result.getCurrent()); |
| | | pageData.setCapacity(result.getSize()); |
| | | return pageData; |
| | | } |
| | | |
| | | @Override |
| | | public ShopWebDetailVO getShopWebDetail(ShopDetailQueryDTO dto) { |
| | | ShopInfo shop = shopInfoMapper.selectById(dto.getId()); |
| | | if (Objects.isNull(shop) || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | | ShopWebDetailVO vo = new ShopWebDetailVO(); |
| | | vo.setId(shop.getId()); |
| | | vo.setName(shop.getName()); |
| | | vo.setAddress(shop.getAddress()); |
| | | vo.setContent(shop.getContent()); |
| | | |
| | | // 门头照 + 内部照 全路径集合 |
| | | String imgPrefix = getShopPrefix(); |
| | | List<String> images = new ArrayList<>(); |
| | | images.addAll(getImageList(dto.getId(), Constants.FileType.STORE_FRONT.getKey(), imgPrefix)); |
| | | images.addAll(getImageList(dto.getId(), Constants.FileType.STORE_INTERIOR.getKey(), imgPrefix)); |
| | | vo.setImages(images); |
| | | |
| | | // 距离 |
| | | if (dto.getLongitude() != null && dto.getLatitude() != null && shop.getLongitude() != null && shop.getLatitude() != null) { |
| | | double distKm = haversine(dto.getLatitude(), dto.getLongitude(), shop.getLatitude(), shop.getLongitude()); |
| | | vo.setDistanceText(formatDistance(distKm)); |
| | | } |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | public void maintainShopInfo(Integer memberId, ShopInfoMaintainDTO dto) { |
| | | // 门店主键与会员主键一致 |
| | | ShopInfo shop = shopInfoMapper.selectById(memberId); |
| | | if (Objects.isNull(shop) || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | // 需要支付完押金后才可维护(auditStatus >= 2) |
| | | if (shop.getAuditStatus() == null || shop.getAuditStatus() < Constants.TWO) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "请先完成押金支付后再维护门店信息"); |
| | | } |
| | | UpdateWrapper<ShopInfo> updateWrapper = new UpdateWrapper<>(); |
| | | updateWrapper.lambda() |
| | | .eq(ShopInfo::getId, shop.getId()) |
| | | .set(ShopInfo::getUpdateTime, new Date()) |
| | | .set(dto.getCoverImg() != null, ShopInfo::getCoverImg, dto.getCoverImg()) |
| | | .set(dto.getContent() != null, ShopInfo::getContent, dto.getContent()) |
| | | .set(dto.getDepositTypes() != null, ShopInfo::getDepositTypes, dto.getDepositTypes()) |
| | | .set(dto.getFeeStandard() != null, ShopInfo::getFeeStandard, dto.getFeeStandard()) |
| | | .set(dto.getDeliveryArea() != null, ShopInfo::getDeliveryArea, dto.getDeliveryArea()) |
| | | .set(dto.getShopHours() != null, ShopInfo::getShopHours, dto.getShopHours()) |
| | | .set(dto.getBusinessType() != null, ShopInfo::getBusinessType, dto.getBusinessType()); |
| | | shopInfoMapper.update(updateWrapper); |
| | | } |
| | | |
| | | @Override |
| | | public ShopInfoMaintainDTO getShopMaintainInfo(Integer memberId) { |
| | | ShopInfo shop = shopInfoMapper.selectById(memberId); |
| | | if (Objects.isNull(shop) || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) { |
| | | return null; |
| | | } |
| | | ShopInfoMaintainDTO dto = new ShopInfoMaintainDTO(); |
| | | dto.setCoverImg(shop.getCoverImg()); |
| | | dto.setContent(shop.getContent()); |
| | | dto.setDepositTypes(shop.getDepositTypes()); |
| | | dto.setFeeStandard(shop.getFeeStandard()); |
| | | dto.setDeliveryArea(shop.getDeliveryArea()); |
| | | dto.setShopHours(shop.getShopHours()); |
| | | dto.setBusinessType(shop.getBusinessType()); |
| | | return dto; |
| | | } |
| | | |
| | | /** |
| | | * Haversine公式计算两点间距离(km) |
| | | */ |
| | | private double haversine(double lat1, double lng1, double lat2, double lng2) { |
| | | double R = 6371; |
| | | double dLat = Math.toRadians(lat2 - lat1); |
| | | double dLng = Math.toRadians(lng2 - lng1); |
| | | double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) |
| | | + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) |
| | | * Math.sin(dLng / 2) * Math.sin(dLng / 2); |
| | | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); |
| | | return R * c; |
| | | } |
| | | |
| | | /** |
| | | * 格式化距离:小于1km显示米,大于等于1km显示千米(保留1位小数) |
| | | */ |
| | | private String formatDistance(double km) { |
| | | if (km < 1) { |
| | | return Math.round(km * 1000) + "m"; |
| | | } |
| | | return String.format("%.1fkm", km); |
| | | } |
| | | |
| | | /** |
| | | * 获取门店图片前缀 |
| | | */ |
| | | private String getShopPrefix() { |
| | | try { |
| | | return systemDictDataBiz.queryByCode(Constants.OSS, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.SHOP_FILES).getCode(); |
| | | } catch (Exception e) { |
| | | return ""; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取门店指定类型的第一张图片全路径 |
| | | */ |
| | | private String getFirstImage(Integer shopId, int objType, String imgPrefix) { |
| | | QueryWrapper<Multifile> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(Multifile::getObjId, shopId) |
| | | .eq(Multifile::getObjType, objType) |
| | | .eq(Multifile::getIsdeleted, Constants.ZERO) |
| | | .orderByAsc(Multifile::getSortnum) |
| | | .last("limit 1"); |
| | | Multifile f = multifileMapper.selectOne(qw); |
| | | return f != null && StringUtils.isNotBlank(f.getFileurl()) ? imgPrefix + f.getFileurl() : null; |
| | | } |
| | | |
| | | /** |
| | | * 获取门店指定类型的所有图片全路径 |
| | | */ |
| | | private List<String> getImageList(Integer shopId, int objType, String imgPrefix) { |
| | | QueryWrapper<Multifile> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(Multifile::getObjId, shopId) |
| | | .eq(Multifile::getObjType, objType) |
| | | .eq(Multifile::getIsdeleted, Constants.ZERO) |
| | | .orderByAsc(Multifile::getSortnum); |
| | | List<Multifile> files = multifileMapper.selectList(qw); |
| | | List<String> urls = new ArrayList<>(); |
| | | for (Multifile f : files) { |
| | | if (StringUtils.isNotBlank(f.getFileurl())) { |
| | | urls.add(imgPrefix + f.getFileurl()); |
| | | } |
| | | } |
| | | return urls; |
| | | } |
| | | |
| | | @Override |
| | | public ShopCenterVO getShopCenterInfo(Integer shopId) { |
| | | ShopInfo shop = shopInfoMapper.selectById(shopId); |
| | | if (shop == null || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | ShopCenterVO vo = new ShopCenterVO(); |
| | | vo.setShopName(shop.getName()); |
| | | vo.setLinkName(shop.getLinkName()); |
| | | vo.setCompanyType(shop.getCompanyType()); |
| | | vo.setCoverImg(shop.getCoverImg()); |
| | | if (StringUtils.isNotBlank(shop.getCoverImg())) { |
| | | String path = systemDictDataBiz.queryByCode(Constants.OSS, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.SHOP_FILES).getCode(); |
| | | vo.setFullCoverImg(path + shop.getCoverImg()); |
| | | } |
| | | vo.setHasMessage(false); |
| | | // 待核验订单数量(存件门店,status=1) |
| | | Long waitDepositCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getDepositShopId, shopId) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .eq(Orders::getStatus, Constants.OrderStatus.waitDeposit.getStatus())); |
| | | vo.setWaitDepositCount(waitDepositCount.intValue()); |
| | | // 待收货订单数量(取件门店,status IN 4,5) |
| | | Long waitReceiveCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getTakeShopId, shopId) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .in(Orders::getStatus, Constants.OrderStatus.delivering.getStatus(), Constants.OrderStatus.arrived.getStatus())); |
| | | vo.setWaitReceiveCount(waitReceiveCount.intValue()); |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * 商户账号密码登录 |
| | | * @param dto |
| | | * @return |
| | | */ |
| | | @Override |
| | | public ShopLoginVO shopPasswordLogin(ShopLoginDTO dto){ |
| | | if(StringUtils.isBlank(dto.getTelephone()) |
| | | || StringUtils.isBlank(dto.getPassword()) |
| | | || StringUtils.isBlank(dto.getOpenid()) |
| | | ){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"用户名或密码不能为空"); |
| | | } |
| | | ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda().eq(ShopInfo::getTelephone, dto.getTelephone()) |
| | | .eq(ShopInfo::getDeleted,Constants.ZERO) |
| | | .last("limit 1") |
| | | ); |
| | | if(shop==null){ |
| | | throw new BusinessException(ResponseStatus.ACCOUNT_INCORRECT); |
| | | } |
| | | //加密密码 |
| | | String pwd = Utils.Secure.encryptPassword( dto.getPassword(), shop.getSalt()); |
| | | if(!pwd.equals(shop.getPassword())){ |
| | | throw new BusinessException(ResponseStatus.ACCOUNT_INCORRECT); |
| | | } |
| | | |
| | | // 更新当前登录会员的openid到门店 |
| | | if(StringUtils.isNotBlank(dto.getOpenid())){ |
| | | shopInfoMapper.update(null,new UpdateWrapper<ShopInfo>().lambda() |
| | | .set(ShopInfo::getOpenid,dto.getOpenid()) |
| | | .eq(ShopInfo::getId,shop.getId()) |
| | | ); |
| | | // 清空其他门店的同一openid,保证唯一 |
| | | shopInfoMapper.update(null,new UpdateWrapper<ShopInfo>().lambda() |
| | | .set(ShopInfo::getOpenid,null) |
| | | .eq(ShopInfo::getOpenid,dto.getOpenid()) |
| | | .ne(ShopInfo::getId,shop.getId()) |
| | | ); |
| | | shop.setOpenid(dto.getOpenid()); |
| | | } |
| | | |
| | | // 创建token(generateTokenForRedis 已自动清除该用户旧token,保证唯一有效) |
| | | String token = JwtTokenUtil.generateTokenForRedis(shop.getId(), Constants.TWO, JSONObject.toJSONString(shop), redisTemplate); |
| | | |
| | | // 构建响应 |
| | | ShopLoginVO vo = new ShopLoginVO(); |
| | | vo.setToken(token); |
| | | vo.setShopId(shop.getId()); |
| | | vo.setShopName(shop.getName()); |
| | | vo.setCompanyType(shop.getCompanyType()); |
| | | |
| | | // 所属城市名称 |
| | | Areas area = areasBiz.resolveArea(shop.getAreaId()); |
| | | if (area != null) { |
| | | vo.setCityName(area.getCityName()); |
| | | } |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | public ShopLoginVO shopSilentLogin(String openid) { |
| | | if (StringUtils.isBlank(openid)) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "openid不能为空"); |
| | | } |
| | | ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda() |
| | | .eq(ShopInfo::getOpenid, openid) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (shop == null) { |
| | | return null; |
| | | } |
| | | |
| | | // 创建token(generateTokenForRedis 已自动清除该用户旧token,保证唯一有效) |
| | | String token = JwtTokenUtil.generateTokenForRedis(shop.getId(), Constants.TWO, JSONObject.toJSONString(shop), redisTemplate); |
| | | |
| | | ShopLoginVO vo = new ShopLoginVO(); |
| | | vo.setToken(token); |
| | | vo.setShopId(shop.getId()); |
| | | vo.setShopName(shop.getName()); |
| | | vo.setCompanyType(shop.getCompanyType()); |
| | | |
| | | Areas area = areasBiz.resolveArea(shop.getAreaId()); |
| | | if (area != null) { |
| | | vo.setCityName(area.getCityName()); |
| | | } |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * 校验城市定价规则配置是否完整 |
| | | * @param cityId 城市主键 |
| | | * @return 错误信息列表,空表示校验通过 |
| | | */ |
| | | private List<String> validateCityPricingRules(Integer cityId) { |
| | | List<String> errors = new ArrayList<>(); |
| | | |
| | | // type=0 就地存取规则:至少1条,fieldB不为空 |
| | | List<PricingRule> type0 = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.ZERO) |
| | | .eq(PricingRule::getCityId, cityId)); |
| | | if (type0.isEmpty()) { |
| | | errors.add("缺少就地存取规则"); |
| | | } else if (type0.stream().allMatch(r -> StringUtils.isBlank(r.getFieldB()))) { |
| | | errors.add("就地存取规则未配置收费单价"); |
| | | } |
| | | |
| | | // type=1 异地寄送规则:至少1条,fieldB/C/D/E不为空 |
| | | List<PricingRule> type1 = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.ONE) |
| | | .eq(PricingRule::getCityId, cityId)); |
| | | if (type1.isEmpty()) { |
| | | errors.add("缺少异地寄送规则"); |
| | | } else if (type1.stream().allMatch(r -> StringUtils.isAnyBlank(r.getFieldB(), r.getFieldC(), r.getFieldD(), r.getFieldE()))) { |
| | | errors.add("异地寄送规则配置不完整"); |
| | | } |
| | | |
| | | // type=2 预计时效:fieldA=1(标速达) 和 fieldA=2(极速达) 各1条 |
| | | List<PricingRule> type2 = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.TWO) |
| | | .eq(PricingRule::getCityId, cityId)); |
| | | Map<String, PricingRule> type2Map = type2.stream() |
| | | .collect(Collectors.toMap(PricingRule::getFieldA, r -> r, (a, b) -> a)); |
| | | if (!type2Map.containsKey("1")) { |
| | | errors.add("缺少预计时效-标速达配置"); |
| | | } else if (StringUtils.isAnyBlank(type2Map.get("1").getFieldB(), type2Map.get("1").getFieldC(), |
| | | type2Map.get("1").getFieldD(), type2Map.get("1").getFieldE())) { |
| | | errors.add("预计时效-标速达配置不完整"); |
| | | } |
| | | if (!type2Map.containsKey("2")) { |
| | | errors.add("缺少预计时效-极速达配置"); |
| | | } else if (StringUtils.isAnyBlank(type2Map.get("2").getFieldB(), type2Map.get("2").getFieldC(), |
| | | type2Map.get("2").getFieldD(), type2Map.get("2").getFieldE())) { |
| | | errors.add("预计时效-极速达配置不完整"); |
| | | } |
| | | |
| | | // type=3 门店注册押金:fieldA=0(企业) 和 fieldA=1(个人) 各1条,fieldB不为空 |
| | | List<PricingRule> type3 = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.THREE) |
| | | .eq(PricingRule::getCityId, cityId)); |
| | | Map<String, PricingRule> type3Map = type3.stream() |
| | | .collect(Collectors.toMap(PricingRule::getFieldA, r -> r, (a, b) -> a)); |
| | | String[] depositNames = {"企业", "个人"}; |
| | | for (int i = 0; i <= 1; i++) { |
| | | String key = String.valueOf(i); |
| | | if (!type3Map.containsKey(key)) { |
| | | errors.add("缺少门店注册押金-" + depositNames[i] + "配置"); |
| | | } else if (StringUtils.isBlank(type3Map.get(key).getFieldB())) { |
| | | errors.add("门店注册押金-" + depositNames[i] + "未配置押金金额"); |
| | | } |
| | | } |
| | | |
| | | // type=4 分成比例:fieldA=0~4 共5条,fieldB不为空 |
| | | List<PricingRule> type4 = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.FOUR) |
| | | .eq(PricingRule::getCityId, cityId)); |
| | | String[] shareNames = {"企业寄", "个人寄", "企业取", "个人取", "配送员"}; |
| | | Map<String, PricingRule> type4Map = type4.stream() |
| | | .collect(Collectors.toMap(PricingRule::getFieldA, r -> r, (a, b) -> a)); |
| | | for (int i = 0; i <= 4; i++) { |
| | | String key = String.valueOf(i); |
| | | if (!type4Map.containsKey(key)) { |
| | | errors.add("缺少分成比例-" + shareNames[i] + "配置"); |
| | | } else if (StringUtils.isBlank(type4Map.get(key).getFieldB())) { |
| | | errors.add("分成比例-" + shareNames[i] + "未配置分成比例"); |
| | | } |
| | | } |
| | | |
| | | return errors; |
| | | } |
| | | |
| | | } |