|
|
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
@@ -12,25 +13,16 @@ import com.ylx.common.core.domain.R;
|
|
|
import com.ylx.common.core.domain.entity.SysDictData;
|
|
|
import com.ylx.common.core.domain.model.WxLoginUser;
|
|
|
import com.ylx.common.exception.ServiceException;
|
|
|
-import com.ylx.common.utils.DateUtils;
|
|
|
-import com.ylx.common.utils.DictUtils;
|
|
|
-import com.ylx.common.utils.SecurityUtils;
|
|
|
-import com.ylx.common.utils.StringUtils;
|
|
|
+import com.ylx.common.utils.*;
|
|
|
import com.ylx.common.weixinPay.enums.WxPayTypeEnum;
|
|
|
import com.ylx.common.weixinPay.service.WxPayV3Service;
|
|
|
-import com.ylx.massage.domain.MaProject;
|
|
|
-import com.ylx.massage.domain.MaTechnician;
|
|
|
-import com.ylx.massage.domain.TAddress;
|
|
|
-import com.ylx.massage.domain.TWxUser;
|
|
|
+import com.ylx.massage.domain.*;
|
|
|
import com.ylx.massage.domain.vo.HomeBlock;
|
|
|
import com.ylx.massage.domain.vo.OrderVerificationVo;
|
|
|
import com.ylx.massage.domain.vo.TechnicianAvailabilityVo;
|
|
|
import com.ylx.massage.mapper.MaProjectMapper;
|
|
|
import com.ylx.massage.mapper.MaTechnicianMapper;
|
|
|
-import com.ylx.massage.service.CouponService;
|
|
|
-import com.ylx.massage.service.IMaTechnicianService;
|
|
|
-import com.ylx.massage.service.TAddressService;
|
|
|
-import com.ylx.massage.service.TWxUserService;
|
|
|
+import com.ylx.massage.service.*;
|
|
|
import com.ylx.massage.utils.OrderNumberGenerator;
|
|
|
import com.ylx.message.enums.TriggerEventEnum;
|
|
|
import com.ylx.message.service.IMessageService;
|
|
|
@@ -41,6 +33,8 @@ import com.ylx.order.domain.dto.*;
|
|
|
import com.ylx.order.domain.vo.OrderDateQueryVo;
|
|
|
import com.ylx.order.domain.vo.OrderDetailVO;
|
|
|
import com.ylx.order.domain.vo.OrderStatusFlowVO;
|
|
|
+import com.ylx.order.domain.vo.merchant.MerchantCancelOrderDTO;
|
|
|
+import com.ylx.order.domain.vo.merchant.OrderCustomerPhoneVO;
|
|
|
import com.ylx.order.domain.vo.merchant.OrderPageVO;
|
|
|
import com.ylx.order.enums.AfterSaleServiceStatusEnum;
|
|
|
import com.ylx.order.enums.OrderStatusEnum;
|
|
|
@@ -57,6 +51,7 @@ import com.ylx.shopingfundsdetail.enums.ShoppingFundsExpenseTypeEnum;
|
|
|
import com.ylx.shopingfundsdetail.service.ShoppingFundsDetailService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
@@ -120,6 +115,14 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
|
|
|
private IMessageService messageService;
|
|
|
|
|
|
private static final int NOT_DELETE = 0;
|
|
|
+ @Resource
|
|
|
+ private TGeoFenceService geoFenceService;
|
|
|
+
|
|
|
+ @Value("${ylx.sendSmsEnabled:false}")
|
|
|
+ private boolean sendSmsEnabled;
|
|
|
+
|
|
|
+ @Value("${ylx.fixedVerifyCode:123456}")
|
|
|
+ private String fixedVerifyCode;
|
|
|
|
|
|
@Override
|
|
|
public TOrder addOrder(TOrder order) {
|
|
|
@@ -554,16 +557,16 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
|
|
|
order.setPaymentMethod(dto.getPaymentMethod());
|
|
|
|
|
|
// 经纬度安全赋值
|
|
|
- order.setUserLatitude(new BigDecimal(address.getLatitude()));
|
|
|
- order.setUserLongitude(new BigDecimal(address.getLongitude()));
|
|
|
+ order.setUserLatitude(address.getLatitude());
|
|
|
+ order.setUserLongitude(address.getLongitude());
|
|
|
|
|
|
merchantAddressList.stream().filter(a -> a.getType() == 1).findFirst().ifPresent(addr -> {
|
|
|
- order.setMerchantLongitude(new BigDecimal(addr.getLongitude()));
|
|
|
- order.setMerchantLatitude(new BigDecimal(addr.getLatitude()));
|
|
|
+ order.setMerchantLongitude(addr.getLongitude());
|
|
|
+ order.setMerchantLatitude(addr.getLatitude());
|
|
|
});
|
|
|
merchantAddressList.stream().filter(a -> a.getType() == 2).findFirst().ifPresent(addr -> {
|
|
|
- order.setVirtualLongitude(new BigDecimal(addr.getLongitude()));
|
|
|
- order.setVirtualLatitude(new BigDecimal(addr.getLatitude()));
|
|
|
+ order.setVirtualLongitude(addr.getLongitude());
|
|
|
+ order.setVirtualLatitude(addr.getLatitude());
|
|
|
});
|
|
|
|
|
|
// 设置支付状态
|
|
|
@@ -905,19 +908,88 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
|
|
|
.eq(TAddress::getIsDefault, 1)
|
|
|
.eq(TAddress::getIsDelete, NOT_DELETE));
|
|
|
if (CollUtil.isEmpty(merchantAddressList)) {
|
|
|
- throw new ServiceException("商户地址不存在");
|
|
|
+ throw new ServiceException("商户地址不存在,请先完善商户地址");
|
|
|
}
|
|
|
|
|
|
- TAddress address = CollUtil.getFirst(merchantAddressList);
|
|
|
- dto.setLongitude(address.getLongitude());
|
|
|
- dto.setLatitude(address.getLatitude());
|
|
|
+ TAddress merchantAddress = CollUtil.getFirst(merchantAddressList);
|
|
|
+ BigDecimal merchantLat = merchantAddress.getLatitude();
|
|
|
+ BigDecimal merchantLon = merchantAddress.getLongitude();
|
|
|
+
|
|
|
+ // 商户坐标为空拦截
|
|
|
+ if (ObjectUtil.hasNull(merchantLat, merchantLon)) {
|
|
|
+ log.warn("商户id:{} 默认地址经纬度为空,无法计算围栏距离", userId);
|
|
|
+ dto.setLatitude(null);
|
|
|
+ dto.setLongitude(null);
|
|
|
+ } else {
|
|
|
+ dto.setLatitude(merchantLat);
|
|
|
+ dto.setLongitude(merchantLon);
|
|
|
+ }
|
|
|
|
|
|
page = this.baseMapper.queryMerchantOrderList(page, dto);
|
|
|
+ List<OrderPageVO> records = page.getRecords();
|
|
|
+ if (CollUtil.isEmpty(records)) {
|
|
|
+ return page;
|
|
|
+ }
|
|
|
|
|
|
- if (ObjectUtil.isNotNull(page) && CollUtil.isNotEmpty(page.getRecords())) {
|
|
|
- List<OrderPageVO> records = page.getRecords();
|
|
|
- for (OrderPageVO record : records) {
|
|
|
- this.fillCurrentAfterSaleInfo(record, record.getId());
|
|
|
+ // 4. 获取所有有效的地理围栏
|
|
|
+ List<TGeoFence> validFenceList = geoFenceService.selectValidFences(dto.getCityCode());
|
|
|
+ if (CollUtil.isEmpty(validFenceList)) {
|
|
|
+ log.info("城市编码{}无有效地理围栏,全部订单非高风险", dto.getCityCode());
|
|
|
+ for (OrderPageVO vo : records) {
|
|
|
+ vo.setIsHighRiskArea(false);
|
|
|
+ }
|
|
|
+ return page;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 遍历订单,在内存中进行空间计算
|
|
|
+ for (OrderPageVO orderVO : records) {
|
|
|
+ BigDecimal userLat = orderVO.getUserLatitude();
|
|
|
+ BigDecimal userLon = orderVO.getUserLongitude();
|
|
|
+ // 用户坐标为空,跳过计算
|
|
|
+ if (ObjectUtil.hasNull(userLat, userLon)) {
|
|
|
+ orderVO.setIsHighRiskArea(false);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 存储最小距离、对应围栏、是否命中风险圈
|
|
|
+ BigDecimal minDistanceKm = null;
|
|
|
+ TGeoFence nearestFence = null;
|
|
|
+
|
|
|
+ for (TGeoFence fence : validFenceList) {
|
|
|
+ BigDecimal fenceLat = fence.getLatitude();
|
|
|
+ BigDecimal fenceLon = fence.getLongitude();
|
|
|
+ BigDecimal radiusKm = fence.getRadiusKm();
|
|
|
+ // 围栏坐标/半径非法则跳过当前围栏
|
|
|
+ if (ObjectUtil.hasNull(fenceLat, fenceLon, radiusKm)
|
|
|
+ || radiusKm.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 【修复】传参顺序:用户纬度、用户经度,围栏纬度、围栏经度
|
|
|
+ BigDecimal distKm = DistanceUtil.formatDistanceInKilometers(userLat, userLon, fenceLat, fenceLon);
|
|
|
+ // 距离非法跳过
|
|
|
+ if (ObjectUtil.isNull(distKm)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新全局最小距离围栏
|
|
|
+ if (ObjectUtil.isNull(minDistanceKm) || distKm.compareTo(minDistanceKm) < 0) {
|
|
|
+ minDistanceKm = distKm;
|
|
|
+ nearestFence = fence;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 赋值VO
|
|
|
+ if (ObjectUtil.isNull(minDistanceKm) || ObjectUtil.isNull(nearestFence)) {
|
|
|
+ orderVO.setIsHighRiskArea(false);
|
|
|
+ orderVO.setDistanceKm(null);
|
|
|
+ orderVO.setFenceIntro(null);
|
|
|
+ } else {
|
|
|
+ orderVO.setDistanceKm(minDistanceKm);
|
|
|
+ // 判断是否在围栏半径内
|
|
|
+ int compare = minDistanceKm.compareTo(nearestFence.getRadiusKm());
|
|
|
+ orderVO.setIsHighRiskArea(compare <= 0);
|
|
|
+ orderVO.setFenceIntro(nearestFence.getFenceIntro());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -979,6 +1051,241 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
|
|
|
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public OrderCustomerPhoneVO getCustomerPhoneByOrderId(OrderPhoneQueryDTO dto) {
|
|
|
+ // 1. 获取当前登录商户
|
|
|
+ WxLoginUser wxLoginUser = getCurrentWxLoginUser();
|
|
|
+ Long merchantId = Long.parseLong(wxLoginUser.getId());
|
|
|
+ Long orderId = dto.getOrderId();
|
|
|
+
|
|
|
+ // 2. 查询订单:只查归属商户、未删除、手机号字段
|
|
|
+ TOrder order = baseMapper.selectOne(Wrappers.lambdaQuery(TOrder.class)
|
|
|
+ .select(TOrder::getId, TOrder::getMerchantId, TOrder::getContactPhoneNumber)
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .eq(TOrder::getMerchantId, merchantId)
|
|
|
+ .eq(TOrder::getIsDelete, 0));
|
|
|
+
|
|
|
+ // 3. 校验订单
|
|
|
+ if (ObjectUtil.isNull(order)) {
|
|
|
+ throw new ServiceException("订单不存在或不属于当前商户");
|
|
|
+ }
|
|
|
+ String phone = order.getContactPhoneNumber();
|
|
|
+ if (StrUtil.isBlank(phone)) {
|
|
|
+ throw new ServiceException("该订单未预留客户联系电话");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 封装返回明文手机号
|
|
|
+ OrderCustomerPhoneVO vo = new OrderCustomerPhoneVO();
|
|
|
+ vo.setContactPhoneNumber(phone);
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void merchantCancelOrderToAfterSale(MerchantCancelOrderDTO dto) {
|
|
|
+ // 1. 获取当前登录商户
|
|
|
+ WxLoginUser loginUser = getCurrentWxLoginUser();
|
|
|
+ Long merchantId = Long.parseLong(loginUser.getId());
|
|
|
+ Long orderId = dto.getOrderId();
|
|
|
+ String cancelReason = dto.getCancelReason();
|
|
|
+
|
|
|
+ // 2. 查询订单基础信息
|
|
|
+ TOrder order = baseMapper.selectOne(Wrappers.lambdaQuery(TOrder.class)
|
|
|
+ .select(TOrder::getId, TOrder::getMerchantId, TOrder::getStatus,
|
|
|
+ TOrder::getUserId, TOrder::getFinalAmount, TOrder::getProjectId)
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .eq(TOrder::getMerchantId, merchantId)
|
|
|
+ .eq(TOrder::getIsDelete, NOT_DELETE));
|
|
|
+
|
|
|
+ // 订单不存在/不属于当前商户
|
|
|
+ if (ObjectUtil.isNull(order)) {
|
|
|
+ throw new ServiceException("订单不存在,无法操作");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 状态校验:仅【商户已接单】允许取消转售后
|
|
|
+ Integer statusCode = order.getStatus();
|
|
|
+ OrderStatusEnum orderStatus = OrderStatusEnum.fromCode(statusCode);
|
|
|
+ if (orderStatus == null
|
|
|
+ || (!OrderStatusEnum.PENDING_SERVICE.getCode().equals(statusCode)
|
|
|
+ && !OrderStatusEnum.IN_SERVICE.getCode().equals(statusCode))) {
|
|
|
+ String currentText = OrderStatusEnum.getInfoByCode(statusCode);
|
|
|
+ throw new ServiceException("仅【待服务、服务中】订单可操作,当前订单状态:" + currentText);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 更新订单为售后状态,并发乐观锁校验
|
|
|
+ if (OrderStatusEnum.PENDING_SERVICE.getCode().equals(statusCode)) {
|
|
|
+ // ========== 分支1:待服务 → 退回待派单,无售后、无退款 ==========
|
|
|
+ LambdaUpdateWrapper<TOrder> updateWrapper = Wrappers.lambdaUpdate(TOrder.class)
|
|
|
+ .set(TOrder::getStatus, OrderStatusEnum.PENDING_DISPATCH.getCode())
|
|
|
+ .set(TOrder::getCancelledTime,LocalDateTime.now())
|
|
|
+ .set(TOrder::getCancelledReason, cancelReason)
|
|
|
+ .set(TOrder::getUpdateTime, LocalDateTime.now())
|
|
|
+ .set(TOrder::getUpdateBy,loginUser.getCNickName())
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .eq(TOrder::getStatus, statusCode);
|
|
|
+ int row = baseMapper.update(null, updateWrapper);
|
|
|
+ if (row <= 0) {
|
|
|
+ throw new ServiceException("订单状态已变更,请刷新重试");
|
|
|
+ }
|
|
|
+ } else if (OrderStatusEnum.IN_SERVICE.getCode().equals(statusCode)) {
|
|
|
+ // ========== 分支2:服务中 → 转售后、生成售后单、发起退款 ==========
|
|
|
+ // 1. 更新订单信息
|
|
|
+ LambdaUpdateWrapper<TOrder> updateWrapper = Wrappers.lambdaUpdate(TOrder.class)
|
|
|
+ .set(TOrder::getCancelledTime,LocalDateTime.now())
|
|
|
+ .set(TOrder::getCancelledReason, cancelReason)
|
|
|
+ .set(TOrder::getUpdateTime, LocalDateTime.now())
|
|
|
+ .set(TOrder::getUpdateBy,loginUser.getCNickName())
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .eq(TOrder::getStatus, statusCode);
|
|
|
+ int row = baseMapper.update(null, updateWrapper);
|
|
|
+ if (row <= 0) {
|
|
|
+ throw new ServiceException("订单状态已变更,请刷新重试");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 创建售后单
|
|
|
+ AfterSalesServiceDTO afterSalesServiceDTO = new AfterSalesServiceDTO();
|
|
|
+ afterSalesServiceDTO.setOrderId(orderId);
|
|
|
+ afterSalesServiceDTO.setReason(cancelReason);
|
|
|
+ this.afterSalesServiceService.applyAfterSale(afterSalesServiceDTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void startService(MerchantOrderOperateDTO dto) {
|
|
|
+
|
|
|
+ // 1. 获取当前登录商户
|
|
|
+ WxLoginUser loginUser = getCurrentWxLoginUser();
|
|
|
+ Long merchantId = Long.parseLong(loginUser.getId());
|
|
|
+ Long orderId = dto.getOrderId();
|
|
|
+
|
|
|
+ TOrder order = baseMapper.selectOne(Wrappers.lambdaQuery(TOrder.class)
|
|
|
+ .select(TOrder::getId, TOrder::getMerchantId, TOrder::getStatus,
|
|
|
+ TOrder::getArrivedTime)
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .eq(TOrder::getMerchantId, merchantId)
|
|
|
+ .eq(TOrder::getIsDelete, NOT_DELETE));
|
|
|
+ if (ObjectUtil.isNull(order)) {
|
|
|
+ throw new ServiceException("订单不存在或不属于当前商户");
|
|
|
+ }
|
|
|
+
|
|
|
+ Integer status = order.getStatus();
|
|
|
+ if (!OrderStatusEnum.PENDING_SERVICE.getCode().equals(status)) {
|
|
|
+ throw new ServiceException("仅【待服务】订单可开始服务,当前状态:" + OrderStatusEnum.getInfoByCode(status));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 可选强校验:必须先签到到达才能开始服务
|
|
|
+ if (ObjectUtil.isNull(order.getArrivedTime())) {
|
|
|
+ throw new ServiceException("请先完成到达签到,再开始服务");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新状态+服务开始时间
|
|
|
+ LambdaUpdateWrapper<TOrder> update = Wrappers.lambdaUpdate(TOrder.class)
|
|
|
+ .set(TOrder::getStatus, OrderStatusEnum.IN_SERVICE.getCode())
|
|
|
+ .set(TOrder::getStartTime, LocalDateTime.now())
|
|
|
+ .set(TOrder::getUpdateTime, LocalDateTime.now())
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .set(TOrder::getUpdateBy,loginUser.getCNickName())
|
|
|
+ .eq(TOrder::getStatus, status);
|
|
|
+ int count = baseMapper.update(null, update);
|
|
|
+ if (count <= 0) {
|
|
|
+ throw new ServiceException("订单状态已变更,请刷新重试");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void finishService(MerchantOrderOperateDTO dto) {
|
|
|
+
|
|
|
+ // 1. 获取当前登录商户
|
|
|
+ WxLoginUser loginUser = getCurrentWxLoginUser();
|
|
|
+ Long merchantId = Long.parseLong(loginUser.getId());
|
|
|
+ Long orderId = dto.getOrderId();
|
|
|
+
|
|
|
+ TOrder order = baseMapper.selectOne(Wrappers.lambdaQuery(TOrder.class)
|
|
|
+ .select(TOrder::getId, TOrder::getMerchantId, TOrder::getStatus,
|
|
|
+ TOrder::getStartTime)
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .eq(TOrder::getMerchantId, merchantId)
|
|
|
+ .eq(TOrder::getIsDelete, NOT_DELETE));
|
|
|
+ if (ObjectUtil.isNull(order)) {
|
|
|
+ throw new ServiceException("订单不存在或不属于当前商户");
|
|
|
+ }
|
|
|
+
|
|
|
+ Integer status = order.getStatus();
|
|
|
+ if (!OrderStatusEnum.IN_SERVICE.getCode().equals(status)) {
|
|
|
+ throw new ServiceException("仅【服务中】订单可完成服务,当前状态:" + OrderStatusEnum.getInfoByCode(status));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 必须存在服务开始时间才能结束
|
|
|
+ if (ObjectUtil.isNull(order.getStartTime())) {
|
|
|
+ throw new ServiceException("未开始服务,无法完成");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新状态、结束时间
|
|
|
+ LambdaUpdateWrapper<TOrder> update = Wrappers.lambdaUpdate(TOrder.class)
|
|
|
+ .set(TOrder::getStatus, OrderStatusEnum.COMPLETED.getCode())
|
|
|
+ .set(TOrder::getCompletedTime, LocalDateTime.now())
|
|
|
+ .set(TOrder::getUpdateTime, LocalDateTime.now())
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .set(TOrder::getUpdateBy,loginUser.getCNickName())
|
|
|
+ .eq(TOrder::getStatus, status);
|
|
|
+ int count = baseMapper.update(null, update);
|
|
|
+ if (count <= 0) {
|
|
|
+ throw new ServiceException("订单状态已变更,请刷新重试");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void merchantArriveSign(MerchantOrderOperateDTO dto) {
|
|
|
+
|
|
|
+ // 1. 获取当前登录商户
|
|
|
+ WxLoginUser loginUser = getCurrentWxLoginUser();
|
|
|
+ Long merchantId = Long.parseLong(loginUser.getId());
|
|
|
+ Long orderId = dto.getOrderId();
|
|
|
+ String code = dto.getCode();
|
|
|
+ String phone = dto.getPhone();
|
|
|
+
|
|
|
+ // 手机号或者验证码 校验
|
|
|
+ if (ObjectUtil.hasNull(phone, code)) {
|
|
|
+ throw new ServiceException("手机号或者验证码不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!validateVerifyCode(phone, code)) {
|
|
|
+ throw new ServiceException("验证码错误");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询订单
|
|
|
+ TOrder order = baseMapper.selectOne(Wrappers.lambdaQuery(TOrder.class)
|
|
|
+ .select(TOrder::getId, TOrder::getMerchantId, TOrder::getStatus)
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .eq(TOrder::getMerchantId, merchantId)
|
|
|
+ .eq(TOrder::getIsDelete, NOT_DELETE));
|
|
|
+ if (ObjectUtil.isNull(order)) {
|
|
|
+ throw new ServiceException("订单不存在或不属于当前商户");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 状态仅允许待服务
|
|
|
+ Integer status = order.getStatus();
|
|
|
+ if (!OrderStatusEnum.PENDING_SERVICE.getCode().equals(status)) {
|
|
|
+ throw new ServiceException("仅【待服务】订单可签到到达,当前状态:" + OrderStatusEnum.getInfoByCode(status));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新到达信息
|
|
|
+ LambdaUpdateWrapper<TOrder> update = Wrappers.lambdaUpdate(TOrder.class)
|
|
|
+ .set(TOrder::getArrivedTime, LocalDateTime.now())
|
|
|
+ .set(TOrder::getUpdateTime, LocalDateTime.now())
|
|
|
+ .set(TOrder::getUpdateBy,loginUser.getCNickName())
|
|
|
+ .eq(TOrder::getId, orderId)
|
|
|
+ .eq(TOrder::getStatus, status);
|
|
|
+ int count = baseMapper.update(null, update);
|
|
|
+ if (count <= 0) {
|
|
|
+ throw new ServiceException("订单状态已变更,请刷新重试");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void fillCurrentAfterSaleInfo(IAfterSaleDisplay vo, Long orderId) {
|
|
|
LambdaQueryWrapper<AfterSalesService> wrapper = new LambdaQueryWrapper<>();
|
|
|
wrapper.eq(AfterSalesService::getOrderId, orderId)
|
|
|
@@ -1102,4 +1409,23 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
|
|
|
return order;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 校验验证码
|
|
|
+ *
|
|
|
+ * @param phone 手机号
|
|
|
+ * @param code 用户输入的验证码
|
|
|
+ * @return boolean 校验是否通过
|
|
|
+ */
|
|
|
+ private boolean validateVerifyCode(String phone, String code) {
|
|
|
+ if (sendSmsEnabled) {
|
|
|
+ // TODO: 从Redis或其他存储中获取真实发送的验证码进行校验
|
|
|
+ // String realCode = redisCache.getCacheObject("sms:bindPhone:" + phone);
|
|
|
+ // return code.equals(realCode);
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ // 使用写死的验证码进行校验
|
|
|
+ return fixedVerifyCode.equals(code);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|