MrShi
7 小时以前 59bfd0b8bbbf0ee94ec68e4a3a1a6e536d0ad8fd
Merge branch 'master' of http://139.186.142.91:10010/r/productDev/gtzxinglijicun
已添加1个文件
已修改22个文件
474 ■■■■ 文件已修改
server/admin/src/main/java/com/doumee/api/business/OrdersController.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/admin/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/biz/system/impl/OperationConfigBizImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/config/wx/WxPayV3Service.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/dto/DriverOrderPageDTO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/vo/LocationTagShopCountVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/vo/ManualRefundDetailVO.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/vo/MyOrderDetailVO.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/vo/MyOrderVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/vo/OrderDetailVO.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/vo/OrdersExportVO.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/vo/ShopCenterVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/MemberCouponService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/OrdersService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/CouponServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/DataBoardServiceImpl.java 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/DriverInfoServiceImpl.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/MemberCouponServiceImpl.java 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java 202 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/ShopInfoServiceImpl.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/web/src/main/java/com/doumee/api/web/MemberCouponApi.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/web/src/main/java/com/doumee/api/web/PaymentCallback.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/admin/src/main/java/com/doumee/api/business/OrdersController.java
@@ -12,10 +12,7 @@
import com.doumee.dao.dto.DispatchDTO;
import com.doumee.dao.dto.HandleOrderExceptionDTO;
import com.doumee.dao.dto.ManualRefundDTO;
import com.doumee.dao.vo.OrderDetailVO;
import com.doumee.dao.vo.OrderDispatchVO;
import com.doumee.dao.vo.OrdersExportVO;
import com.doumee.dao.vo.OrderSummaryVO;
import com.doumee.dao.vo.*;
import com.doumee.service.business.OrdersService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -109,6 +106,8 @@
            vo.setOverdueAmount(String.valueOf(Constants.getFormatMoney(o.getOverdueAmount())));
            vo.setExceptionAmount(String.valueOf(Constants.getFormatMoney(o.getExceptionAmount())));
            vo.setDeductionAmount(String.valueOf(Constants.getFormatMoney(o.getDeductionAmount())));
            vo.setShopCompensationAmount(String.valueOf(Constants.getFormatMoney(o.getShopCompensationAmount())));
            vo.setExceptionFee(String.valueOf(Constants.getFormatMoney(o.getExceptionFee())));
            vo.setStatusDesc(o.getStatusDesc());
            vo.setSettlementDesc(o.getSettlementStatus() != null ? (o.getSettlementStatus() == 1 ? "已结算" : "待结算") : "");
            vo.setPayTime(o.getPayTime());
@@ -174,4 +173,11 @@
        return ApiResponse.success("操作成功");
    }
    @ApiOperation("手动退款详情")
    @GetMapping("/manualRefundDetail/{orderId}")
    @RequiresPermissions("business:orders:query")
    public ApiResponse<ManualRefundDetailVO> manualRefundDetail(@PathVariable Integer orderId) {
        return ApiResponse.success(ordersService.getManualRefundDetail(orderId));
    }
}
server/admin/src/main/resources/application.yml
@@ -12,7 +12,7 @@
spring:
  profiles:
    active: dev
    active: pro
  # JSON返回配置
  jackson:
    # é»˜è®¤æ—¶åŒº
server/services/src/main/java/com/doumee/biz/system/impl/OperationConfigBizImpl.java
@@ -50,9 +50,9 @@
        dto.setRegisterCouponId(getValue(Constants.OP_REGISTER_COUPON_ID));
        dto.setRegisterGiftCouponIds(getValue(Constants.OP_REGISTER_GIFT_COUPON_IDS));
        dto.setRegisterRewardOrderCount(getValue(Constants.OP_REGISTER_REWARD_ORDER_COUNT));
        dto.setRegisterRewardAmount(fenToYuan(getValue(Constants.OP_REGISTER_REWARD_AMOUNT)));
        dto.setRegisterRewardAmount(getValue(Constants.OP_REGISTER_REWARD_AMOUNT));
        dto.setPlatformRewardOrderCount(getValue(Constants.OP_PLATFORM_REWARD_ORDER_COUNT));
        dto.setPlatformRewardAmount(fenToYuan(getValue(Constants.OP_PLATFORM_REWARD_AMOUNT)));
        dto.setPlatformRewardAmount(getValue(Constants.OP_PLATFORM_REWARD_AMOUNT));
        dto.setInvoiceMonthLimit(getValue(Constants.OP_INVOICE_MONTH_LIMIT));
        return dto;
    }
server/services/src/main/java/com/doumee/config/wx/WxPayV3Service.java
@@ -59,7 +59,7 @@
            com.wechat.pay.java.service.payments.jsapi.model.Amount amount =
                    new com.wechat.pay.java.service.payments.jsapi.model.Amount();
            amount.setTotal(1);//totalCents.intValue());
            amount.setTotal(totalCents.intValue());
            amount.setCurrency("CNY");
            request.setAmount(amount);
@@ -109,8 +109,8 @@
            request.setNotifyUrl(notifyUrl);
            AmountReq amount = new AmountReq();
            amount.setRefund(1L);//refundCents);
            amount.setTotal(1L);//totalCents);
            amount.setRefund(refundCents);
            amount.setTotal(totalCents);
            amount.setCurrency("CNY");
            request.setAmount(amount);
server/services/src/main/java/com/doumee/dao/dto/DriverOrderPageDTO.java
@@ -16,4 +16,7 @@
    @ApiModelProperty(value = "订单状态筛选:null=全部;3=待取件;4=配送中;7=已完成")
    private Integer status;
    @ApiModelProperty(value = "搜索关键词(收件人/收件人电话模糊/订单号精准)")
    private String keyword;
}
server/services/src/main/java/com/doumee/dao/vo/LocationTagShopCountVO.java
@@ -24,4 +24,7 @@
    @ApiModelProperty("门店数量")
    private Integer shopCount;
    @ApiModelProperty(value = "排序码", hidden = true)
    private Integer sortnum;
}
server/services/src/main/java/com/doumee/dao/vo/ManualRefundDetailVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
package com.doumee.dao.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("手动退款详情")
public class ManualRefundDetailVO {
    @ApiModelProperty(value = "退款金额(分)")
    private Long refundAmount;
    @ApiModelProperty(value = "存件门店扣款金额(分)")
    private Long depositShopDeduct;
    @ApiModelProperty(value = "取件门店扣款金额(分)")
    private Long takeShopDeduct;
    @ApiModelProperty(value = "司机扣款金额(分)")
    private Long driverDeduct;
    @ApiModelProperty(value = "退款备注")
    private String refundRemark;
}
server/services/src/main/java/com/doumee/dao/vo/MyOrderDetailVO.java
@@ -76,6 +76,8 @@
    private Date arriveTime;
    // ---- å­˜ä»¶é—¨åº— ----
    @ApiModelProperty(value = "存件门店主键", example = "1")
    private Integer depositShopId;
    @ApiModelProperty(value = "存件门店名称")
    private String depositShopName;
@@ -132,6 +134,9 @@
    @ApiModelProperty(value = "实际支付费用(分)")
    private Long actualPayAmount;
    @ApiModelProperty(value = "优惠券抵扣金额(分)")
    private Long deductionAmount;
    // ---- é€¾æœŸ ----
    //逾期状态: 0=未到店未逾期 1=未到店存在逾期 2=已到店未存在逾期 3=已到店待支付逾期 4=逾期已支付
server/services/src/main/java/com/doumee/dao/vo/MyOrderVO.java
@@ -148,4 +148,7 @@
    @ApiModelProperty(value = "优惠券抵扣金额(分)")
    private Long deductionAmount;
    @ApiModelProperty(value = "是否异常订单:0=否;1=是")
    private Integer abnormalOrder;
}
server/services/src/main/java/com/doumee/dao/vo/OrderDetailVO.java
@@ -6,6 +6,7 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
@@ -82,4 +83,22 @@
    @ApiModelProperty(value = "优惠券抵扣金额(分)")
    private Long deductionAmount;
    @ApiModelProperty(value = "评价内容")
    private String commentContent;
    @ApiModelProperty(value = "评价时间")
    private Date commentTime;
    @ApiModelProperty(value = "评价附件图片")
    private List<String> commentImages;
    @ApiModelProperty(value = "寄存门店评分")
    private Integer depositScore;
    @ApiModelProperty(value = "取件门店评分")
    private Integer takeScore;
    @ApiModelProperty(value = "司机评分")
    private Integer driverScore;
}
server/services/src/main/java/com/doumee/dao/vo/OrdersExportVO.java
@@ -47,15 +47,21 @@
    @ExcelColumn(name = "优惠券折扣(元)", index = 12)
    private String deductionAmount;
    @ExcelColumn(name = "订单状态", index = 13)
    @ExcelColumn(name = "门店补偿费用(元)", index = 13)
    private String shopCompensationAmount;
    @ExcelColumn(name = "司机补偿费用(元)", index = 14)
    private String exceptionFee;
    @ExcelColumn(name = "订单状态", index = 15)
    private String statusDesc;
    @ExcelColumn(name = "结算状态", index = 14)
    @ExcelColumn(name = "结算状态", index = 16)
    private String settlementDesc;
    @ExcelColumn(name = "支付时间", index = 15, dateFormat = "yyyy-MM-dd HH:mm:ss", width = 16)
    @ExcelColumn(name = "支付时间", index = 17, dateFormat = "yyyy-MM-dd HH:mm:ss", width = 16)
    private Date payTime;
    @ExcelColumn(name = "创建时间", index = 16, dateFormat = "yyyy-MM-dd HH:mm:ss", width = 16)
    @ExcelColumn(name = "创建时间", index = 18, dateFormat = "yyyy-MM-dd HH:mm:ss", width = 16)
    private Date createTime;
}
server/services/src/main/java/com/doumee/dao/vo/ShopCenterVO.java
@@ -6,6 +6,9 @@
@Data
public class ShopCenterVO {
    @ApiModelProperty(value = "门店主键")
    private Integer id;
    @ApiModelProperty(value = "门店头像全路径")
    private String fullCoverImg;
server/services/src/main/java/com/doumee/service/business/MemberCouponService.java
@@ -5,6 +5,7 @@
import com.doumee.dao.business.model.MemberCoupon;
import java.util.List;
import java.util.Map;
public interface MemberCouponService {
@@ -27,4 +28,6 @@
    PageData<MemberCoupon> findMemberPage(Integer memberId, Integer status, PageWrap<MemberCoupon> pageWrap);
    void claimCoupon(Integer memberId, Integer couponId);
    Map<String, Integer> findPendingCount(Integer memberId);
}
server/services/src/main/java/com/doumee/service/business/OrdersService.java
@@ -466,4 +466,5 @@
     */
    Boolean checkOperationRadius(Integer orderId, Integer userId, Integer userType, Double lng, Double lat);
    ManualRefundDetailVO getManualRefundDetail(Integer orderId);
}
server/services/src/main/java/com/doumee/service/business/impl/CouponServiceImpl.java
@@ -164,6 +164,12 @@
        if (coupon.getPrice() >= coupon.getLimitPrice()) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "优惠金额必须小于满额");
        }
        if (coupon.getLimitPrice() < 1000) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "满减金额最低10元");
        }
        if (coupon.getLimitPrice() - coupon.getPrice() < 1000) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "满减金额必须大于扣减金额10元以上");
        }
        if (Objects.isNull(coupon.getPushDays()) || coupon.getPushDays() < 1) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "推送后领取有效天数必须大于等于1天");
        }
server/services/src/main/java/com/doumee/service/business/impl/DataBoardServiceImpl.java
@@ -150,10 +150,10 @@
        Map<String, Long> map = members.stream()
                .collect(Collectors.groupingBy(m -> sdf.format(m.getCreateTime()), Collectors.counting()));
        return buildTrendList(range, (date) -> {
        return buildTrendList(range, (key, label) -> {
            MemberTrendVO vo = new MemberTrendVO();
            vo.setDate(date);
            vo.setCount(map.getOrDefault(date, 0L));
            vo.setDate(label);
            vo.setCount(map.getOrDefault(key, 0L));
            return vo;
        });
    }
@@ -169,10 +169,10 @@
        Map<String, List<Orders>> grouped = orders.stream()
                .collect(Collectors.groupingBy(o -> sdf.format(o.getCreateTime())));
        return buildTrendList(range, (date) -> {
            List<Orders> dayOrders = grouped.getOrDefault(date, Collections.emptyList());
        return buildTrendList(range, (key, label) -> {
            List<Orders> dayOrders = grouped.getOrDefault(key, Collections.emptyList());
            OrderTrendVO vo = new OrderTrendVO();
            vo.setDate(date);
            vo.setDate(label);
            vo.setLocalCount(dayOrders.stream().filter(o -> Constants.equalsInteger(o.getType(), Constants.ZERO)).count());
            vo.setRemoteCount(dayOrders.stream().filter(o -> Constants.equalsInteger(o.getType(), Constants.ONE)).count());
            return vo;
@@ -227,11 +227,11 @@
            }
        }
        return buildTrendList(range, (date) -> {
        return buildTrendList(range, (key, label) -> {
            RevenueTrendVO vo = new RevenueTrendVO();
            vo.setDate(date);
            long local = localOrderRevenue.getOrDefault(date, 0L);
            long remote = remoteOrderRevenue.getOrDefault(date, 0L);
            vo.setDate(label);
            long local = localOrderRevenue.getOrDefault(key, 0L);
            long remote = remoteOrderRevenue.getOrDefault(key, 0L);
            vo.setLocalRevenue(BigDecimal.valueOf(local).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
            vo.setRemoteRevenue(BigDecimal.valueOf(remote).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
            return vo;
@@ -718,7 +718,7 @@
    @FunctionalInterface
    private interface TrendVOBuilder<T> {
        T build(String date);
        T build(String key, String label);
    }
    private <T> List<T> buildTrendList(TrendDateRange range, TrendVOBuilder<T> builder) {
@@ -732,7 +732,8 @@
            Calendar end = Calendar.getInstance();
            end.setTime(range.endDate);
            while (!loop.after(end)) {
                result.add(builder.build(sdf.format(loop.getTime())));
                String dateStr = sdf.format(loop.getTime());
                result.add(builder.build(dateStr, dateStr));
                loop.add(Calendar.DAY_OF_MONTH, 1);
            }
        } else {
@@ -741,8 +742,9 @@
            endCal.setTime(range.endDate);
            int endMonth = endCal.get(Calendar.MONTH); // 0-based
            for (int m = 0; m <= endMonth; m++) {
                String label = String.format("%02d", m + 1);
                result.add(builder.build(label));
                String key = String.format("%02d", m + 1);
                String label = (m + 1) + "月";
                result.add(builder.build(key, label));
            }
        }
        return result;
server/services/src/main/java/com/doumee/service/business/impl/DriverInfoServiceImpl.java
@@ -246,7 +246,6 @@
        IPage<DriverInfo> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
        MPJLambdaWrapper<DriverInfo> queryWrapper = new MPJLambdaWrapper<>();
        Utils.MP.blankToNull(pageWrap.getModel());
        pageWrap.getModel().setDeleted(Constants.ZERO);
        // å¸æœºå§“名/手机号(关键字模糊查询)
        if (StringUtils.isNotBlank(pageWrap.getModel().getKeyword())) {
@@ -282,7 +281,8 @@
        queryWrapper.selectAll(DriverInfo.class)
                .select(" ( select ifnull(sum(r.OPT_TYPE * r.AMOUNT),0) from revenue r where r.MEMBER_TYPE = 1 and r.MEMBER_ID= t.id and r.VAILD_STATUS = 1 ) as memberAmount ")
                .selectAs(Category::getName,DriverInfo::getCarTypeName)
                .leftJoin(Category.class, Category::getId,DriverInfo::getCarType);
                .leftJoin(Category.class, Category::getId,DriverInfo::getCarType)
                .eq(DriverInfo::getDeleted, Constants.ZERO);
        queryWrapper.orderByDesc(DriverInfo::getId);
        PageData<DriverInfo> pageData = PageData.from(driverInfoMapper.selectPage(page, queryWrapper));
        for (DriverInfo d : pageData.getRecords()) {
@@ -560,8 +560,13 @@
            driverInfoMapper.insert(newChange);
            saveDriverAttachments(newChange.getId(), request, now);
            // æ ‡è®°åŽ†å²çš„å˜æ›´ç‰ˆæœ¬ä¸ºåˆ é™¤
            driverInfoMapper.update(new UpdateWrapper<DriverInfo>().lambda()
                    .set(DriverInfo::getDeleted, Constants.ONE)
                    .set(DriverInfo::getUpdateTime, now)
                    .eq(DriverInfo::getMemberId, memberId)
                    .eq(DriverInfo::getVersionType, Constants.ONE)
                    .eq(DriverInfo::getDeleted, Constants.ZERO)
                    .ne(DriverInfo::getId, newChange.getId()));
        } else {
            // auditStatus=0/2:直接更新变更版本
@@ -1881,6 +1886,9 @@
        if (!driverId.equals(order.getAcceptDriver())) {
            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "无权操作该订单");
        }
        if (Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "异常订单无法进行确认送达");
        }
        // 3. ä¿å­˜é€è¾¾å›¾ç‰‡
        Date now = new Date();
@@ -2271,7 +2279,13 @@
                .eq(status != null, Orders::getStatus, status)
                .eq(Orders::getDeleted, Constants.ZERO)
                .orderByDesc(Orders::getAcceptTime);
        // å…³é”®è¯æœç´¢ï¼šæ”¶ä»¶äºº/收件人电话模糊、订单号精准
        if (StringUtils.isNotBlank(model.getKeyword())) {
            String kw = model.getKeyword().trim();
            wrapper.and(w -> w.like(Orders::getTakeUser, kw)
                    .or().like(Orders::getTakePhone, kw)
                    .or().like(Orders::getCode, kw));
        }
        IPage<Orders> orderPage = ordersMapper.selectJoinPage(p, Orders.class, wrapper);
        List<DriverGrabOrderVO> voList = new ArrayList<>();
server/services/src/main/java/com/doumee/service/business/impl/MemberCouponServiceImpl.java
@@ -26,7 +26,9 @@
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Service
@@ -197,6 +199,22 @@
    }
    @Override
    public Map<String, Integer> findPendingCount(Integer memberId) {
        Long waitClaim = memberCouponMapper.selectCount(new QueryWrapper<MemberCoupon>().lambda()
                .eq(MemberCoupon::getMemberId, memberId)
                .eq(MemberCoupon::getStatus, Constants.CouponStatus.waitClaim.getKey())
                .eq(MemberCoupon::getIsdeleted, Constants.ZERO));
        Long waitUse = memberCouponMapper.selectCount(new QueryWrapper<MemberCoupon>().lambda()
                .eq(MemberCoupon::getMemberId, memberId)
                .eq(MemberCoupon::getStatus, Constants.CouponStatus.claimed.getKey())
                .eq(MemberCoupon::getIsdeleted, Constants.ZERO));
        Map<String, Integer> result = new LinkedHashMap<>();
        result.put("waitClaim", waitClaim != null ? waitClaim.intValue() : 0);
        result.put("waitUse", waitUse != null ? waitUse.intValue() : 0);
        return result;
    }
    @Override
    @Transactional(rollbackFor = {Exception.class, BusinessException.class})
    public void claimCoupon(Integer memberId, Integer couponId) {
        // æŸ¥è¯¢è¯¥ä¼šå‘˜çš„待领取优惠券记录
@@ -207,11 +225,6 @@
                .eq(MemberCoupon::getIsdeleted, Constants.ZERO));
        if (mc == null) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        // æ ¡éªŒä¼˜æƒ åˆ¸æ˜¯å¦æœ‰æ•ˆ
        Coupon coupon = couponMapper.selectById(couponId);
        if (coupon == null || coupon.getStatus() != Constants.ZERO) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "优惠券无效");
        }
        // æ ‡è®°å·²é¢†å–,计算有效期
        Date now = new Date();
server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
@@ -410,9 +410,9 @@
            }
        }
        // æ ¹æ®openid查询当前绑定的门店
        if (StringUtils.isNotBlank(member.getOpenid())) {
        if (Objects.nonNull(member.getLoginShopId())) {
            ShopInfo bindShop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
                    .eq(ShopInfo::getOpenid, member.getOpenid())
                    .eq(ShopInfo::getId, member.getLoginShopId())
                    .eq(ShopInfo::getDeleted, Constants.ZERO)
                    .last("limit 1"));
            if (bindShop != null) {
@@ -725,6 +725,12 @@
        );
    }
    /**
     * æ³¨å†Œæ»¡X年赠送优惠券(定时任务调用)
     * è§„则:根据运营配置 registerCouponYears(满几年赠送)、registerCouponGiftCount(至多赠送次数)、registerCouponId(赠送优惠券ID列表),
     * éåŽ†æ‰€æœ‰æ™®é€šä¼šå‘˜ï¼Œè®¡ç®—æ³¨å†Œå¹´é™ï¼Œæ¯æ»¡é…ç½®å¹´æ•°èµ é€ä¸€æ¬¡ï¼Œç´¯è®¡èµ é€æ¬¡æ•°ä¸è¶…è¿‡é…ç½®ä¸Šé™ã€‚
     * ä¾‹å¦‚:配置满2年赠送、至多3次,则注册第2/4/6年各赠送一次,共3次。
     */
    @Override
    public void giftRegisterCoupon() {
        // 1. è¯»å–配置
@@ -753,11 +759,17 @@
            return;
        }
        // 3. æŸ¥è¯¢æ‰€æœ‰æ™®é€šä¼šå‘˜
        // 3. æ•°æ®åº“层面过滤:注册满configYears且未赠满的普通会员
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.YEAR, -configYears);
        Date minRegisterDate = cal.getTime();
        List<Member> members = memberMapper.selectList(new QueryWrapper<Member>().lambda()
                .eq(Member::getDeleted, Constants.ZERO)
                .eq(Member::getStatus, Constants.ZERO)
                .eq(Member::getUserType, Constants.ZERO)
                .le(Member::getCreateTime, minRegisterDate)
                .lt(Member::getRegisterCouponGiftCount, maxGiftCount)
                .isNotNull(Member::getCreateTime));
        Date now = new Date();
server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
@@ -133,6 +133,8 @@
    @Autowired
    private MemberCouponMapper memberCouponMapper;
    @Autowired
    private CouponMapper couponMapper;
    @Autowired
    private AreasBiz areasBiz;
@@ -662,7 +664,7 @@
                .le(MemberCoupon::getLimitPrice, totalPrice)
                .ge(MemberCoupon::getEndDate, now)
                .orderByDesc(MemberCoupon::getPrice)
                .orderByAsc(MemberCoupon::getEndDate));
                .orderByAsc(MemberCoupon::getCreateDate));
        result.setAvailableCoupons(availableCoupons);
        if (couponId == null) {
@@ -1151,6 +1153,11 @@
        if (Objects.isNull(order)) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        // å®žä»˜é‡‘额 = æ”¯ä»˜é‡‘额 - é€€æ¬¾é‡‘额 + é€¾æœŸè´¹ç”¨
        long pay = order.getPayAmount() != null ? order.getPayAmount() : 0L;
        long refund = order.getRefundAmount() != null ? order.getRefundAmount() : 0L;
        long overdue = order.getOverdueAmount() != null ? order.getOverdueAmount() : 0L;
        order.setPayAmount(pay - refund + overdue);
        OrderDetailVO vo = new OrderDetailVO();
        vo.setOrder(order);
@@ -1217,6 +1224,25 @@
            for (OrderItemVO v:vo.getDetailList()) {
                v.setTypeName(category.getName());
            }
        }
        // è¯„价信息
        List<OrderComment> comments = orderCommentMapper.selectList(new QueryWrapper<OrderComment>().lambda()
                .eq(OrderComment::getOrderId, id)
                .eq(OrderComment::getDeleted, Constants.ZERO));
        if (CollectionUtils.isNotEmpty(comments)) {
            for (OrderComment c : comments) {
                if (Constants.equalsInteger(c.getTargetType(), Constants.ONE)) {
                    vo.setDepositScore(c.getScore());
                } else if (Constants.equalsInteger(c.getTargetType(), Constants.TWO)) {
                    vo.setTakeScore(c.getScore());
                } else if (Constants.equalsInteger(c.getTargetType(), Constants.THREE)) {
                    vo.setDriverScore(c.getScore());
                }
            }
            vo.setCommentContent(comments.get(0).getContent());
            vo.setCommentTime(comments.get(0).getCreateTime());
            vo.setCommentImages(getFileUrls(id, Constants.FileType.COMMENT_ATTACH.getKey(), imgPrefix));
        }
        // å–消/退款状态时查询退款记录
@@ -1655,7 +1681,8 @@
                cal.set(Calendar.MINUTE, 0);
                cal.set(Calendar.SECOND, 0);
                cal.set(Calendar.MILLISECOND, 0);
                wrapper.ge(Orders::getFinishTime, cal.getTime());
                wrapper.ge(Orders::getFinishTime, cal.getTime())
                        .eq(Orders::getStatus, Constants.OrderStatus.finished.getKey());
            }
        }
        // å…³é”®è¯æœç´¢ï¼šæ”¶ä»¶äºº/收件人电话模糊、订单号精准
@@ -1737,6 +1764,8 @@
                fillOverdueStatus(vo, o, details);
                // ä¼˜æƒ åˆ¸æŠµæ‰£é‡‘额
                vo.setDeductionAmount(o.getDeductionAmount());
                // å¼‚常订单标识
                vo.setAbnormalOrder(o.getExceptionStatus());
                // å¯å¼€ç¥¨é‡‘额(支付金额 - é€€æ¬¾é‡‘额)
                if (model != null && model.getInvoiceStatus() != null && Constants.equalsInteger(model.getInvoiceStatus(), Constants.ONE)) {
                    long payAmt = o.getPayAmount() != null ? o.getPayAmount() : 0L;
@@ -1815,7 +1844,7 @@
                    .or(w3-> w3.eq(Orders::getType, Constants.ONE).eq(Orders::getDepositShopId, shopId)
                            .eq(Orders::getStatus, Constants.OrderStatus.waitDeposit.getStatus()))
                    .or(w2 -> w2.eq(Orders::getType, Constants.ONE).eq(Orders::getTakeShopId, shopId)
                            .eq(Orders::getStatus, Constants.OrderStatus.arrived.getStatus())))
                            .in(Orders::getStatus, Constants.OrderStatus.arrived.getStatus(),Constants.OrderStatus.delivering.getStatus())))
            );
        } else {
            wrapper.and(w -> w.eq(Orders::getDepositShopId, shopId).or().eq(Orders::getTakeShopId, shopId));
@@ -1975,6 +2004,7 @@
        vo.setUrgentAmount(order.getUrgentAmount());
        vo.setIsUrgent(order.getIsUrgent());
        vo.setActualPayAmount(Constants.equalsInteger(order.getPayStatus(), Constants.ONE)?order.getPayAmount():order.getEstimatedAmount());
        vo.setDeductionAmount(order.getDeductionAmount());
        // æ ‡è®°
        vo.setExceptionStatus(order.getExceptionStatus());
@@ -1988,13 +2018,12 @@
            vo.setPayCountdownMs(calcPayCountdownMs(order));
        }
        //序号
        vo.setSortnum(Constants.formatIntegerNum(order.getDepositShopId())+"-"+order.getId());
        if(order.getTakeShopId()!=null){
            String dateStr = new SimpleDateFormat("dd").format(order.getPayTime() != null ? order.getPayTime() : new Date());
            String autoNumStr = String.format("%03d", order.getAutoNum() != null ? order.getAutoNum() : 0);
            String sort = order.getTakeShopId() + "-" + dateStr + "-" + autoNumStr;
            vo.setSortnumTake(sort);
        }
//        vo.setSortnum(Constants.formatIntegerNum(order.getDepositShopId())+"-"+order.getId());
        String dateStr = new SimpleDateFormat("dd").format(order.getPayTime() != null ? order.getPayTime() : new Date());
        String autoNumStr = String.format("%03d", order.getAutoNum() != null ? order.getAutoNum() : 0);
        String sort = order.getDepositShopId() + "-" + dateStr + "-" + autoNumStr;
        vo.setSortnum(sort);
        vo.setDepositShopId(order.getDepositShopId());
        // å­˜ä»¶é—¨åº—
        if (order.getDepositShopId() != null) {
            ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId());
@@ -2282,16 +2311,71 @@
     * ä¿å­˜å–消订单操作日志
     */
    private void restoreCoupon(Orders order) {
//        if (order.getCouponId() == null || order.getDeductionAmount() == null || order.getDeductionAmount() <= 0) {
//            return;
//        }
//        memberCouponMapper.update(new UpdateWrapper<MemberCoupon>().lambda()
//                .set(MemberCoupon::getStatus, Constants.CouponStatus.claimed.getKey())
//                .set(MemberCoupon::getUseDate, null)
//                .set(MemberCoupon::getOrderId, null)
//                .eq(MemberCoupon::getId, order.getCouponId())
//                .eq(MemberCoupon::getOrderId, order.getId())
//                .eq(MemberCoupon::getStatus, Constants.CouponStatus.used.getKey()));
        if (order.getCouponId() == null || order.getDeductionAmount() == null || order.getDeductionAmount() <= 0) {
            return;
        }
        memberCouponMapper.update(new UpdateWrapper<MemberCoupon>().lambda()
                .set(MemberCoupon::getStatus, Constants.CouponStatus.claimed.getKey())
                .set(MemberCoupon::getUseDate, null)
                .set(MemberCoupon::getOrderId, null)
                .eq(MemberCoupon::getId, order.getCouponId())
                .eq(MemberCoupon::getOrderId, order.getId())
                .eq(MemberCoupon::getStatus, Constants.CouponStatus.used.getKey()));
    }
    private void giftOrderCoupon(Integer memberId) {
        String orderCountStr = operationConfigBiz.getConfig().getOrderCouponOrderCount();
        String giftCountStr = operationConfigBiz.getConfig().getOrderCouponGiftCount();
        String couponIdsStr = operationConfigBiz.getConfig().getOrderCouponId();
        if (StringUtils.isAnyBlank(orderCountStr, giftCountStr, couponIdsStr)) return;
        int orderCount = Integer.parseInt(orderCountStr);
        int maxGift = Integer.parseInt(giftCountStr);
        Member member = memberMapper.selectById(memberId);
        if (member == null) return;
        int gifted = member.getOrderCouponGiftCount() != null ? member.getOrderCouponGiftCount() : 0;
        if (gifted >= maxGift) return;
        long completedCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda()
                .eq(Orders::getMemberId, memberId)
                .eq(Orders::getDeleted, Constants.ZERO)
                .notIn(Orders::getStatus,
                        Constants.OrderStatus.waitPay.getKey(),
                        Constants.OrderStatus.waitDeposit.getKey()));
        if (completedCount < orderCount || completedCount % orderCount != 0) return;
        String[] idArr = couponIdsStr.split(",");
        Date now = new Date();
        for (String idStr : idArr) {
            String trimmed = idStr.trim();
            if (StringUtils.isBlank(trimmed)) continue;
            Coupon coupon = couponMapper.selectById(Integer.valueOf(trimmed));
            if (coupon == null || Constants.equalsInteger(coupon.getIsdeleted(), Constants.ONE)) continue;
            MemberCoupon mc = new MemberCoupon();
            mc.setCouponId(coupon.getId());
            mc.setMemberId(memberId);
            mc.setStatus(Constants.CouponStatus.waitClaim.getKey());
            Calendar validCal = Calendar.getInstance();
            validCal.add(Calendar.DAY_OF_MONTH, coupon.getPushDays() != null ? coupon.getPushDays() : 7);
            mc.setValidDate(validCal.getTime());
            mc.setName(coupon.getName());
            mc.setInfo(coupon.getInfo());
            mc.setType(coupon.getType());
            mc.setLimitPrice(coupon.getLimitPrice());
            mc.setPrice(coupon.getPrice());
            mc.setGetMethod(coupon.getGetMethod());
            mc.setCouponType(coupon.getCouponType());
            mc.setPushDays(coupon.getPushDays());
            mc.setValidDays(coupon.getValidDays());
            mc.setIsdeleted(Constants.ZERO);
            mc.setCreateDate(now);
            mc.setEditDate(now);
            memberCouponMapper.insert(mc);
        }
        member.setOrderCouponGiftCount(gifted + 1);
        memberMapper.updateById(member);
    }
    private void saveCancelLog(Orders order, Constants.OrderLogType logType, String reason, Integer memberId) {
@@ -2406,7 +2490,7 @@
                refund.setRefundTime(now);
                ordersRefundMapper.updateById(refund);
                // é€€æ¬¾æˆåŠŸï¼Œæ‰§è¡Œæ‰£æ¬¾
                processManualRefundDeduction(order, depositShopDeduct, takeShopDeduct, driverDeduct);
                //processManualRefundDeduction(order, depositShopDeduct, takeShopDeduct, driverDeduct);
            } else if (com.wechat.pay.java.service.refund.model.Status.PROCESSING.equals(refundStatus)) {
                refund.setStatus(Constants.ZERO); // é€€æ¬¾ä¸­ï¼Œç­‰å›žè°ƒ
                ordersRefundMapper.updateById(refund);
@@ -2428,7 +2512,6 @@
        // 7. æ›´æ–°è®¢å•:标记已手动退款,累加退款金额
        ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                .set(Orders::getManualRefund, Constants.ONE)
                .setSql(" REFUND_AMOUNT = IFNULL(REFUND_AMOUNT, 0) + " + dto.getRefundAmount())
                .set(Orders::getUpdateTime, now)
                .eq(Orders::getId, order.getId()));
    }
@@ -2511,10 +2594,11 @@
        Long driverDeduct = deductJson.getLong("driverDeduct");
        processManualRefundDeduction(order, depositShopDeduct, takeShopDeduct, driverDeduct);
        // æ ‡è®°è®¢å•已手动退款,累加退款金额
        // æ ‡è®°è®¢å•已手动退款,累加退款金额,同步更新totalAmount
        ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                .set(Orders::getManualRefund, Constants.ONE)
                .setSql(" REFUND_AMOUNT = IFNULL(REFUND_AMOUNT, 0) + " + refundRecord.getRefundAmount())
                .setSql(" TOTAL_AMOUNT = IFNULL(TOTAL_AMOUNT, 0) - " + refundRecord.getRefundAmount())
                .set(Orders::getUpdateTime, new Date())
                .eq(Orders::getId, order.getId()));
    }
@@ -3262,6 +3346,8 @@
                sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.WAIT_PICKUP_REMIND, order.getId(),
                        "orderNo", order.getCode(), "shopName", shopName);
            }
            // å¯„存成功赠送优惠券
            giftOrderCoupon(order.getMemberId());
        } else if (Constants.equalsInteger(status, Constants.OrderStatus.arrived.getStatus())) {
            // å¼‚地寄存 + æ— å–件门店 â†’ æ— æ³•核销(客户自取,无门店操作)
            if (Constants.equalsInteger(order.getType(), Constants.ONE) && order.getTakeShopId() == null) {
@@ -3881,14 +3967,16 @@
            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "核销码无效");
        }
        // ä»…异地寄存 + æœ‰å–件门店 + æ´¾é€ä¸­(4) å¯æ ¸é”€
        if (!Constants.equalsInteger(order.getType(), Constants.ONE)) {
        // ä»…异地寄存 + æœ‰å–件门店 + æ´¾é€ä¸­(4) å¯æ ¸é”€ï¼ˆå¼‚常订单允许)
        if (!Constants.equalsInteger(order.getType(), Constants.ONE)
                && !Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅异地寄存订单支持司机核销");
        }
        if (order.getTakeShopId() == null) {
        if (order.getTakeShopId() == null && !Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单无取件门店,无需司机核销");
        }
        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.delivering.getStatus())) {
        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.delivering.getStatus())
                && !Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.deposited.getStatus())) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前订单状态不允许核销");
        }
@@ -4601,7 +4689,7 @@
                    sendSmsNotify(member != null ? member.getTelephone() : null,
                            Constants.SmsNotify.MEMBER_CANCELLED, "orderNo", order.getCode());
                }
                restoreCoupon(order);
                count++;
            } catch (Exception e) {
                log.error("取消超时订单异常, orderId={}, error={}", order.getId(), e.getMessage());
@@ -5019,29 +5107,26 @@
                }
                targetLat = order.getDepositLat();
                targetLgt = order.getDepositLgt();
            } else if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())) {
                // status=5 é—¨åº—完成核销
                if (Constants.equalsInteger(order.getType(), Constants.ZERO)) {
                    // å°±åœ°å­˜å– â†’ å¯¹æ¯”存件门店
                    if (!Constants.equalsInteger(order.getDepositShopId(), userId)) {
                        throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
                    }
                    targetLat = order.getDepositLat();
                    targetLgt = order.getDepositLgt();
                } else {
                    // å¼‚地存取 â†’ å¯¹æ¯”取件门店
                    if (!Constants.equalsInteger(order.getTakeShopId(), userId)) {
                        throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
                    }
                    targetLat = order.getTakeLat();
                    targetLgt = order.getTakeLgt();
            } else if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())&&Constants.equalsInteger(order.getType(), Constants.ZERO)) {
                // å°±åœ°å­˜å– â†’ å¯¹æ¯”存件门店
                if (!Constants.equalsInteger(order.getDepositShopId(), userId)) {
                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
                }
                targetLat = order.getDepositLat();
                targetLgt = order.getDepositLgt();
            } else if ((Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.delivering.getStatus())||Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus()))&&Constants.equalsInteger(order.getType(), Constants.ONE)) {
                // å¼‚地存取 â†’ å¯¹æ¯”取件门店
                if (!Constants.equalsInteger(order.getTakeShopId(), userId)) {
                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
                }
                targetLat = order.getTakeLat();
                targetLgt = order.getTakeLgt();
            } else {
                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单状态不允许此操作");
            }
        } else if (Constants.equalsInteger(userType, Constants.ONE)) {
            // å¸æœºæ“ä½œ
            if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.deposited.getStatus())) {
            if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.accepted.getStatus())) {
                // status=2 å¸æœºå–ä»¶
                if (!Constants.equalsInteger(order.getAcceptDriver(), userId)) {
                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
@@ -5082,8 +5167,8 @@
        if (original.getTakeShopId() != null) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单已关联取件门店,不支持异常处理");
        }
        if (!Constants.equalsInteger(original.getStatus(), Constants.FIVE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅支持已送达状态的订单");
        if (!Constants.equalsInteger(original.getStatus(), Constants.OrderStatus.delivering.getKey())) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅支持配送中的订单进行异常处理");
        }
        if (Constants.equalsInteger(original.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单已处理过异常,请勿重复操作");
@@ -5299,4 +5384,27 @@
        }
    }
    @Override
    public ManualRefundDetailVO getManualRefundDetail(Integer orderId) {
        OrdersRefund refundRecord = ordersRefundMapper.selectOne(new QueryWrapper<OrdersRefund>().lambda()
                .eq(OrdersRefund::getOrderId, orderId)
                .eq(OrdersRefund::getType, Constants.FOUR)
                .eq(OrdersRefund::getDeleted, Constants.ZERO)
                .orderByDesc(OrdersRefund::getCreateTime)
                .last("limit 1"));
        if (refundRecord == null) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        ManualRefundDetailVO vo = new ManualRefundDetailVO();
        vo.setRefundAmount(refundRecord.getRefundAmount());
        if (StringUtils.isNotBlank(refundRecord.getDeductInfo())) {
            JSONObject json = JSONObject.parseObject(refundRecord.getDeductInfo());
            vo.setDepositShopDeduct(json.getLong("depositShopDeduct"));
            vo.setTakeShopDeduct(json.getLong("takeShopDeduct"));
            vo.setDriverDeduct(json.getLong("driverDeduct"));
        }
        vo.setRefundRemark(refundRecord.getRefundRemark());
        return vo;
    }
}
server/services/src/main/java/com/doumee/service/business/impl/ShopInfoServiceImpl.java
@@ -19,6 +19,7 @@
import com.doumee.dao.business.MemberMapper;
import com.doumee.dao.business.MultifileMapper;
import com.doumee.dao.business.OrdersMapper;
import com.doumee.dao.business.OtherOrdersMapper;
import com.doumee.dao.business.PricingRuleMapper;
import com.doumee.dao.business.RevenueMapper;
import com.doumee.dao.business.ShopInfoMapper;
@@ -27,6 +28,7 @@
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.OtherOrders;
import com.doumee.dao.business.model.PricingRule;
import com.doumee.dao.business.model.Revenue;
import com.doumee.dao.business.model.ShopInfo;
@@ -122,6 +124,9 @@
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private OtherOrdersMapper otherOrdersMapper;
    @Override
    public Integer create(ShopInfo shopInfo) {
@@ -342,6 +347,8 @@
            newChange.setCreateTime(now);
            newChange.setUpdateTime(now);
            newChange.setRegionMemberId(member.getId());
            newChange.setRevenueShareConfig(changeVersion.getRevenueShareConfig());
            newChange.setDeliveryArea(changeVersion.getDeliveryArea());
            setDepositAmountFromPricingRule(newChange);
            shopInfoMapper.insert(newChange);
@@ -564,6 +571,7 @@
                changeVersion.setAuditUserId(auditDTO.getAuditUser());
                changeVersion.setRevenueShareConfig(revenueShareConfig);
                changeVersion.setUpdateTime(now);
                setDefaultDeliveryRange(changeVersion);
                shopInfoMapper.updateById(changeVersion);
                // æ ‡è®°åŽ†å²çš„å˜æ›´ç‰ˆæœ¬ä¸ºåˆ é™¤
@@ -1213,8 +1221,20 @@
            vo.setTagId(tag.getId());
            vo.setTagName(tag.getName());
            vo.setShopCount(count != null ? count.intValue() : 0);
            vo.setSortnum(tag.getSortnum());
            result.add(vo);
        }
        // æŒ‰é—¨åº—数量倒序,相同时按排序码降序
        result.sort((a, b) -> {
            int cmp = Integer.compare(
                    b.getShopCount() != null ? b.getShopCount() : 0,
                    a.getShopCount() != null ? a.getShopCount() : 0);
            if (cmp != 0) return cmp;
            return Integer.compare(
                    b.getSortnum() != null ? b.getSortnum() : 0,
                    a.getSortnum() != null ? a.getSortnum() : 0);
        });
        // æ€»æ•°æ”¾åœ¨åˆ—表第一个
        Long totalCount = shopInfoMapper.selectCount(baseQw);
@@ -1396,6 +1416,7 @@
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        ShopCenterVO vo = new ShopCenterVO();
        vo.setId(shop.getId());
        vo.setShopName(shop.getName());
        vo.setLinkName(shop.getLinkName());
        vo.setCompanyType(shop.getCompanyType());
@@ -1597,14 +1618,34 @@
                .count();
        vo.setFinishedOrderCount((int) finishedCount);
        // æ€»è¥æ”¶é‡‘额 = sum(totalAmount - refundAmount)
        long totalRevenue = orders.stream()
        // æ€»è¥æ”¶é‡‘额 = sum(支付金额 - é€€æ¬¾é‡‘额) + é€¾æœŸé‡‘额
        long baseRevenue = orders.stream()
                .mapToLong(o -> {
                    long total = o.getTotalAmount() != null ? o.getTotalAmount() : 0L;
                    long pay = o.getPayAmount() != null ? o.getPayAmount() : 0L;
                    long refund = o.getRefundAmount() != null ? o.getRefundAmount() : 0L;
                    return total - refund;
                    return pay - refund;
                }).sum();
        vo.setTotalRevenue(totalRevenue);
        // æŸ¥è¯¢è¯¥é—¨åº—参与的逾期费用(从other_orders表获取,type=2已支付)
        QueryWrapper<OtherOrders> overdueQw = new QueryWrapper<>();
        overdueQw.lambda()
                .eq(OtherOrders::getDeleted, Constants.ZERO)
                .eq(OtherOrders::getType, Constants.TWO)
                .eq(OtherOrders::getPayStatus, Constants.ONE)
                .inSql(OtherOrders::getOrderId,
                        "SELECT id FROM orders WHERE DELETED = 0 AND (DEPOSIT_SHOP_ID = " + shopId + " OR TAKE_SHOP_ID = " + shopId + ")");
        if (query.getStartDate() != null) {
            overdueQw.lambda().ge(OtherOrders::getCreateTime, query.getStartDate());
        }
        if (query.getEndDate() != null) {
            overdueQw.lambda().le(OtherOrders::getCreateTime, Utils.Date.getEnd(query.getEndDate()));
        }
        List<OtherOrders> overdueOrders = otherOrdersMapper.selectList(overdueQw);
        long overdueTotal = overdueOrders.stream()
                .mapToLong(o -> o.getPayAccount() != null ? o.getPayAccount() : 0L)
                .sum();
        vo.setTotalRevenue(baseRevenue + overdueTotal);
        // é—¨åº—分成金额
        long shopFee = 0L;
server/web/src/main/java/com/doumee/api/web/MemberCouponApi.java
@@ -14,6 +14,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@Slf4j
@Api(tags = "会员优惠券")
@RestController
@@ -35,6 +37,16 @@
    }
    @LoginRequired
    @ApiOperation(value = "待领取/待使用数量", notes = "角标用")
    @GetMapping("/pendingCount")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true),
    })
    public ApiResponse<Map<String, Integer>> pendingCount() {
        return ApiResponse.success("操作成功", memberCouponService.findPendingCount(getMemberId()));
    }
    @LoginRequired
    @ApiOperation(value = "领取优惠券", notes = "小程序端")
    @GetMapping("/claim")
    @ApiImplicitParams({
server/web/src/main/java/com/doumee/api/web/PaymentCallback.java
@@ -202,7 +202,8 @@
                    log.info("退款记录状态已更新, refundRecordId={}, status={}", refundRecord.getId(), refundRecord.getStatus());
                    // æ‰‹åŠ¨é€€æ¬¾(type=4)退款成功 â†’ æ‰§è¡Œæ‰£æ¬¾
                    if (Status.SUCCESS.equals(refundStatus) && Constants.equalsInteger(refundRecord.getType(), Constants.FOUR)) {
                    if (Status.SUCCESS.equals(refundStatus)
                            && Constants.equalsInteger(refundRecord.getType(), Constants.FOUR)) {
                        try {
                            ordersService.processManualRefundCallback(refundRecord);
                        } catch (Exception ex) {