ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TRefundApplicationController.java
@@ -14,6 +14,7 @@ import com.ruoyi.system.export.TPhysicalGoodsImport; import com.ruoyi.system.model.*; import com.ruoyi.system.query.BigGiftPackageQuery; import com.ruoyi.system.query.RefundApplicationQuery; import com.ruoyi.system.service.TAppUserService; import com.ruoyi.system.service.TBigGiftPackageOrderService; import com.ruoyi.system.service.TBigGiftPackageService; @@ -48,21 +49,17 @@ private final TRefundApplicationService tRefundApplicationService; private final TokenService tokenService; private final TBigGiftPackageOrderService tBigGiftPackageOrderService; private final TAppUserService tAppUserService; private final TBigGiftPackageService tBigGiftPackageService; public TRefundApplicationController(TRefundApplicationService tRefundApplicationService, TokenService tokenService, TBigGiftPackageOrderService tBigGiftPackageOrderService, TAppUserService tAppUserService, TBigGiftPackageService tBigGiftPackageService) { public TRefundApplicationController(TRefundApplicationService tRefundApplicationService, TokenService tokenService, TBigGiftPackageOrderService tBigGiftPackageOrderService) { this.tRefundApplicationService = tRefundApplicationService; this.tokenService = tokenService; this.tBigGiftPackageOrderService = tBigGiftPackageOrderService; this.tAppUserService = tAppUserService; this.tBigGiftPackageService = tBigGiftPackageService; } @ApiOperation(value = "退款申请列表") @PostMapping(value = "/pageRefundList") public R<Page<TBigGiftPackageOrder>> pageRefundList(@RequestBody BigGiftPackageQuery query) { public R<Page<TBigGiftPackageOrder>> pageRefundList(@RequestBody RefundApplicationQuery query) { Page<TBigGiftPackageOrder> page = tRefundApplicationService.pageRefundList(query); return R.ok(page); } @@ -71,50 +68,7 @@ @ApiOperation(value = "退款申请详情") @GetMapping(value = "/refundDetail/{id}") public R<TRefundApplicationVo> refundDetail(@PathVariable Integer id) { TRefundApplication refundApplication = tRefundApplicationService.getById(id); TRefundApplicationVo vo = new TRefundApplicationVo(); vo.setId(refundApplication.getId()); vo.setBigGiftPackageOrderId(refundApplication.getBigGiftPackageOrderId()); // 订单信息 TBigGiftPackageOrder order = tBigGiftPackageOrderService.getById(refundApplication.getBigGiftPackageOrderId()); vo.setCode(order.getCode()); vo.setCreateTime(order.getCreateTime()); vo.setOrderPrice(order.getOrderPrice()); // 用户信息 TAppUser appUser = tAppUserService.getById(order.getAppUserId()); vo.setUserName(appUser.getName()); vo.setPhone(appUser.getPhone()); // 商品信息 TBigGiftPackage tBigGiftPackage = tBigGiftPackageService.getById(order.getBigGiftPackageId()); vo.setBigGiftPackageName(tBigGiftPackage.getName()); vo.setBigGiftPackageCover(tBigGiftPackage.getCoverImage()); vo.setBigGiftPackagePrice(tBigGiftPackage.getTotalPrice()); vo.setBigGiftPackageIntro(tBigGiftPackage.getIntroduction()); // 销量 long count = tBigGiftPackageOrderService.count(new LambdaQueryWrapper<TBigGiftPackageOrder>().eq(TBigGiftPackageOrder::getBigGiftPackageId, order.getBigGiftPackageId()).ne(TBigGiftPackageOrder::getStatus, 5)); vo.setBigGiftPackageSales((int)count); // 支付信息 vo.setStatus(order.getStatus()); vo.setOrderAmount(order.getOrderPrice()); vo.setFinalPayment(order.getFinalPayment()); vo.setPaidTime(order.getFinalPaymentTime()); vo.setRemark(order.getRemark()); // 退款信息 vo.setRefundReason(refundApplication.getRefundReason()); vo.setVoucherPicture(refundApplication.getVoucherPicture()); vo.setRefundStatus(refundApplication.getStatus()); // 审核信息 vo.setAuditRemark(refundApplication.getAuditRemark()); vo.setAuditTime(refundApplication.getAuditTime()); return R.ok(vo); return R.ok(tRefundApplicationService.refundDetail(id)); } @ApiOperation(value = "退款申请删除") ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/agent/AgentBigGiftPackageOrderController.java
@@ -14,20 +14,24 @@ import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.WebUtils; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.system.dto.RefundApplyDTO; import com.ruoyi.system.dto.TransferOrderDto; import com.ruoyi.system.export.TBigGiftPackageOrderExport; import com.ruoyi.system.model.*; import com.ruoyi.system.query.AppUserListQuery; import com.ruoyi.system.query.BigGiftPackageOrderQuery; import com.ruoyi.system.query.OrderTransferQuery; import com.ruoyi.system.query.RefundApplicationQuery; import com.ruoyi.system.service.*; import com.ruoyi.system.vo.TOrderTransferDetailVo; import com.ruoyi.system.vo.TOrderTransferVo; import com.ruoyi.system.vo.TRefundApplicationVo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.apache.poi.ss.usermodel.Workbook; import org.springframework.context.annotation.Lazy; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.ServletOutputStream; @@ -56,6 +60,7 @@ private final TAppUserService tAppUserService; private final TCompanyService tCompanyService; private final TBigGiftPackageService tBigGiftPackageService; private final TRefundApplicationService tRefundApplicationService; @ApiOperation(value = "大礼包订单列表") @@ -117,6 +122,32 @@ return R.ok(tBigGiftPackageOrder); } @ApiOperation(value = "大礼包订单退款申请") @PostMapping(value = "/applyRefund") public R<Void> applyRefund(@Validated @RequestBody RefundApplyDTO dto) { if (!SecurityUtils.isAgentUser()) { throw new ServiceException("请使用经销商/股东帐号访问"); } Integer userId = SecurityUtils.getLoginUser().getUser().getUserId().intValue(); tRefundApplicationService.applyRefund(dto, userId); return R.ok(); } @ApiOperation(value = "退款申请记录列表") @PostMapping(value = "/refundList") public R<Page<TBigGiftPackageOrder>> refundList(@RequestBody RefundApplicationQuery query) { if (!SecurityUtils.isAgentUser()) { throw new ServiceException("请使用经销商/股东帐号访问"); } query.setCompanyId(SecurityUtils.getLoginUser().getUser().getCompanyId()); Page<TBigGiftPackageOrder> page = tRefundApplicationService.pageRefundList(query); return R.ok(page); } @ApiOperation(value = "退款申请详情") @GetMapping(value = "/refundDetail/{id}") public R<TRefundApplicationVo> refundDetail(@PathVariable Integer id) { return R.ok(tRefundApplicationService.refundDetail(id)); } } ruoyi-system/src/main/java/com/ruoyi/system/dto/RefundApplyDTO.java
New file @@ -0,0 +1,30 @@ package com.ruoyi.system.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * 退款申请参数DTO * * @author xiaochen * @since 2025-12-24 */ @Data @ApiModel("退款申请参数DTO") public class RefundApplyDTO { @NotNull(message = "订单ID不能为空") @ApiModelProperty(value = "大礼包订单ID", required = true) private Integer orderId; @NotBlank(message = "退款原因不能为空") @ApiModelProperty(value = "退款原因", required = true) private String refundReason; @ApiModelProperty(value = "凭证图片(多张图片用逗号分隔)") private String voucherPicture; } ruoyi-system/src/main/java/com/ruoyi/system/mapper/TRefundApplicationMapper.java
@@ -5,6 +5,7 @@ import com.ruoyi.system.model.TRefundApplication; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.system.query.BigGiftPackageQuery; import com.ruoyi.system.query.RefundApplicationQuery; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -19,7 +20,7 @@ */ public interface TRefundApplicationMapper extends BaseMapper<TRefundApplication> { Page<TBigGiftPackageOrder> pageRefundList(@Param("page") Page<TBigGiftPackageOrder> page, @Param("query") BigGiftPackageQuery query); Page<TBigGiftPackageOrder> pageRefundList(@Param("page") Page<TBigGiftPackageOrder> page, @Param("query") RefundApplicationQuery query); List<TBigGiftPackageOrder> pageRefundExportList(@Param("query") BigGiftPackageQuery query); ruoyi-system/src/main/java/com/ruoyi/system/query/RefundApplicationQuery.java
New file @@ -0,0 +1,35 @@ package com.ruoyi.system.query; import com.ruoyi.common.core.domain.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * 退款申请查询参数 * * @author xiaochen * @since 2025-12-24 */ @Data @ApiModel("退款申请查询参数") public class RefundApplicationQuery extends BasePage { @ApiModelProperty(value = "订单编号") private String code; @ApiModelProperty(value = "用户手机号") private String phone; @ApiModelProperty(value = "下单时间(2025-01-01 - 2025-02-02)") private String time; @ApiModelProperty(value = "审核状态(1=待审核,2=审核通过,3=审核驳回)") private Integer auditStatus; @ApiModelProperty(value = "公司ID") private Integer companyId; @ApiModelProperty(value = "名称") private String name; } ruoyi-system/src/main/java/com/ruoyi/system/service/TRefundApplicationService.java
@@ -4,7 +4,10 @@ import com.ruoyi.system.model.TBigGiftPackageOrder; import com.ruoyi.system.model.TRefundApplication; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.system.dto.RefundApplyDTO; import com.ruoyi.system.query.BigGiftPackageQuery; import com.ruoyi.system.query.RefundApplicationQuery; import com.ruoyi.system.vo.TRefundApplicationVo; import java.util.List; @@ -19,10 +22,18 @@ public interface TRefundApplicationService extends IService<TRefundApplication> { Page<TBigGiftPackageOrder> pageRefundList(BigGiftPackageQuery query); Page<TBigGiftPackageOrder> pageRefundList(RefundApplicationQuery query); List<TBigGiftPackageOrder> pageRefundExportList(BigGiftPackageQuery query); /** * 提交退款申请 * * @param dto 退款申请参数 * @param userId 申请人用户ID */ void applyRefund(RefundApplyDTO dto, Integer userId); TRefundApplicationVo refundDetail(Integer id); } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ICBCNotifyServiceImpl.java
@@ -11,9 +11,11 @@ import com.ruoyi.system.config.ICBCConfig; import com.ruoyi.system.enums.BigGiftPackageOrderStatusEnum; import com.ruoyi.system.enums.PhysicalGoodsOrderStatusEnum; import com.ruoyi.system.model.TAppUser; import com.ruoyi.system.model.TBigGiftPackageOrder; import com.ruoyi.system.model.TPhysicalGoodsOrder; import com.ruoyi.system.service.*; import com.ruoyi.common.core.domain.entity.SysUser; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; @@ -46,6 +48,10 @@ private final TPhysicalGoodsOrderService physicalGoodsOrderService; private final TCommissionTransactionFlowService commissionTransactionFlowService; private final TAppUserService appUserService; private final ISysUserService sysUserService; @Override @Transactional(rollbackFor = Exception.class) @@ -159,6 +165,9 @@ order.getAppUserId() ); log.info("订单{}分佣计算完成", order.getCode()); // 处理用户推荐状态和公司关联 processUserReferrerAndCompany(order.getAppUserId()); } else { log.error("尾款支付订单号{}【工商银行】大礼包尾款支付失败,错误信息:{}", finalPayOrderCode, bizContent.getString("return_msg")); } @@ -216,6 +225,9 @@ physicalGoodsOrderService.updateById(order); log.info("订单{}状态更新为完成支付", orderCode); // 处理用户推荐状态和公司关联 processUserReferrerAndCompany(order.getAppUserId()); } else { log.error("订单{}【工商银行】实物商品支付失败,错误信息:{}", orderCode, bizContent.getString("return_msg")); order.setStatus(PhysicalGoodsOrderStatusEnum.CANCELED.getCode()); @@ -268,6 +280,9 @@ // 启用生效日,不计算分佣(由定时任务处理) log.info("订单{}启用生效日,延迟计算分佣", order.getCode()); } // 处理用户推荐状态和公司关联 processUserReferrerAndCompany(order.getAppUserId()); } } @@ -355,4 +370,65 @@ } } /** * 处理用户推荐状态和公司关联 * 支付成功后调用此方法更新用户信息 * * @param appUserId 下单用户ID */ private void processUserReferrerAndCompany(Integer appUserId) { if (appUserId == null) { return; } TAppUser appUser = appUserService.getById(appUserId); if (appUser == null) { log.warn("用户{}不存在,跳过推荐状态和公司关联处理", appUserId); return; } boolean needUpdate = false; // 1. 更新推荐状态:如果 referrerUserId 不为空且 referrerStatus=1,则更新为 referrerStatus=2 if (appUser.getReferrerUserId() != null && Integer.valueOf(1).equals(appUser.getReferrerStatus())) { appUser.setReferrerStatus(2); needUpdate = true; log.info("用户{}推荐状态从临时(1)更新为正式(2)", appUserId); } // 2. 关联公司:如果用户 companyId 为空 if (appUser.getCompanyId() == null) { Integer companyId = null; // 优先使用 referrerSysUserId 对应的 SysUser 的 companyId if (appUser.getReferrerSysUserId() != null) { SysUser sysUser = sysUserService.selectUserById(Long.valueOf(appUser.getReferrerSysUserId())); if (sysUser != null && sysUser.getCompanyId() != null) { companyId = sysUser.getCompanyId(); log.info("用户{}通过股东(SysUser:{})关联公司{}", appUserId, appUser.getReferrerSysUserId(), companyId); } } // 如果 referrerSysUserId 为空或对应的 SysUser 没有 companyId,则使用 referrerUserId 对应的 TAppUser 的 companyId if (companyId == null && appUser.getReferrerUserId() != null) { TAppUser referrerAppUser = appUserService.getById(appUser.getReferrerUserId()); if (referrerAppUser != null && referrerAppUser.getCompanyId() != null) { companyId = referrerAppUser.getCompanyId(); log.info("用户{}通过推荐人(TAppUser:{})关联公司{}", appUserId, appUser.getReferrerUserId(), companyId); } } if (companyId != null) { appUser.setCompanyId(companyId); needUpdate = true; } } // 3. 更新用户信息 if (needUpdate) { appUserService.updateById(appUser); log.info("用户{}信息更新完成,referrerStatus={},companyId={}", appUserId, appUser.getReferrerStatus(), appUser.getCompanyId()); } } } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TRefundApplicationServiceImpl.java
@@ -1,15 +1,29 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.system.dto.RefundApplyDTO; import com.ruoyi.system.enums.BigGiftPackageOrderStatusEnum; import com.ruoyi.system.model.TAppUser; import com.ruoyi.system.model.TBigGiftPackage; import com.ruoyi.system.model.TBigGiftPackageOrder; import com.ruoyi.system.model.TRefundApplication; import com.ruoyi.system.mapper.TRefundApplicationMapper; import com.ruoyi.system.query.BigGiftPackageQuery; import com.ruoyi.system.query.RefundApplicationQuery; import com.ruoyi.system.service.TAppUserService; import com.ruoyi.system.service.TBigGiftPackageOrderService; import com.ruoyi.system.service.TBigGiftPackageService; import com.ruoyi.system.service.TRefundApplicationService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.system.vo.TRefundApplicationVo; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.time.LocalDateTime; import java.util.List; /** @@ -21,10 +35,15 @@ * @since 2025-12-08 */ @Service @RequiredArgsConstructor(onConstructor_ = @Lazy) public class TRefundApplicationServiceImpl extends ServiceImpl<TRefundApplicationMapper, TRefundApplication> implements TRefundApplicationService { private final TBigGiftPackageOrderService tBigGiftPackageOrderService; private final TAppUserService tAppUserService; private final TBigGiftPackageService tBigGiftPackageService; @Override public Page<TBigGiftPackageOrder> pageRefundList(BigGiftPackageQuery query) { public Page<TBigGiftPackageOrder> pageRefundList(RefundApplicationQuery query) { Page<TBigGiftPackageOrder> page = new Page<>(query.getPageNum(), query.getPageSize()); return this.baseMapper.pageRefundList(page, query); } @@ -33,4 +52,91 @@ public List<TBigGiftPackageOrder> pageRefundExportList(BigGiftPackageQuery query) { return this.baseMapper.pageRefundExportList(query); } @Override @Transactional(rollbackFor = Exception.class) public void applyRefund(RefundApplyDTO dto, Integer userId) { // 校验订单是否存在 TBigGiftPackageOrder order = tBigGiftPackageOrderService.getById(dto.getOrderId()); if (order == null) { throw new ServiceException("订单不存在"); } // 校验订单状态:只有已付订金、完成支付、确认收货的订单可以申请退款 Integer status = order.getStatus(); boolean canApplyRefund = status.equals(BigGiftPackageOrderStatusEnum.DEPOSIT_PAID.getCode()) || status.equals(BigGiftPackageOrderStatusEnum.PAID.getCode()) || status.equals(BigGiftPackageOrderStatusEnum.CONFIRM_RECEIPT.getCode()); if (!canApplyRefund) { throw new ServiceException("当前订单状态不支持退款申请"); } // 校验是否已存在待审核的退款申请 long pendingCount = this.count(new LambdaQueryWrapper<TRefundApplication>() .eq(TRefundApplication::getBigGiftPackageOrderId, dto.getOrderId()) .eq(TRefundApplication::getStatus, 1) .eq(TRefundApplication::getDelFlag, 0)); if (pendingCount > 0) { throw new ServiceException("该订单已存在待审核的退款申请"); } // 创建退款申请记录 TRefundApplication refundApplication = new TRefundApplication(); refundApplication.setBigGiftPackageOrderId(dto.getOrderId()); refundApplication.setApplicantUserId(userId); refundApplication.setApplicantTime(LocalDateTime.now()); refundApplication.setRefundReason(dto.getRefundReason()); refundApplication.setVoucherPicture(dto.getVoucherPicture()); refundApplication.setStatus(1); // 待审核 refundApplication.setDelFlag(0); this.save(refundApplication); } @Override public TRefundApplicationVo refundDetail(Integer id) { TRefundApplication refundApplication = this.getById(id); TRefundApplicationVo vo = new TRefundApplicationVo(); vo.setId(refundApplication.getId()); vo.setBigGiftPackageOrderId(refundApplication.getBigGiftPackageOrderId()); // 订单信息 TBigGiftPackageOrder order = tBigGiftPackageOrderService.getById(refundApplication.getBigGiftPackageOrderId()); vo.setCode(order.getCode()); vo.setCreateTime(order.getCreateTime()); vo.setOrderPrice(order.getOrderPrice()); // 用户信息 TAppUser appUser = tAppUserService.getById(order.getAppUserId()); vo.setUserName(appUser.getName()); vo.setPhone(appUser.getPhone()); // 商品信息 TBigGiftPackage tBigGiftPackage = tBigGiftPackageService.getById(order.getBigGiftPackageId()); vo.setBigGiftPackageName(tBigGiftPackage.getName()); vo.setBigGiftPackageCover(tBigGiftPackage.getCoverImage()); vo.setBigGiftPackagePrice(tBigGiftPackage.getTotalPrice()); vo.setBigGiftPackageIntro(tBigGiftPackage.getIntroduction()); // 销量 long count = tBigGiftPackageOrderService.count(new LambdaQueryWrapper<TBigGiftPackageOrder>().eq(TBigGiftPackageOrder::getBigGiftPackageId, order.getBigGiftPackageId()).ne(TBigGiftPackageOrder::getStatus, 5)); vo.setBigGiftPackageSales((int)count); // 支付信息 vo.setStatus(order.getStatus()); vo.setOrderAmount(order.getOrderPrice()); vo.setFinalPayment(order.getFinalPayment()); vo.setPaidTime(order.getFinalPaymentTime()); vo.setRemark(order.getRemark()); // 退款信息 vo.setRefundReason(refundApplication.getRefundReason()); vo.setVoucherPicture(refundApplication.getVoucherPicture()); vo.setRefundStatus(refundApplication.getStatus()); // 审核信息 vo.setAuditRemark(refundApplication.getAuditRemark()); vo.setAuditTime(refundApplication.getAuditTime()); return vo; } } ruoyi-system/src/main/resources/mapper/system/TRefundApplicationMapper.xml
@@ -24,6 +24,21 @@ select t1.id,t2.code,t2.create_time,t3.name userName,t3.phone,t2.order_price,t4.name bigGiftPackageName,t2.payment_type,t2.deposit,t2.final_payment,t1.status auditStatus from t_refund_application t1 left join t_big_gift_package_order t2 on t1.big_gift_package_order_id = t2.id left join t_app_user t3 on t2.app_user_id = t3.id left join t_big_gift_package t4 on t2.big_gift_package_id = t4.id where t1.del_flag = 0 <if test="query.code != null and query.code != ''"> and t2.code like concat('%',#{query.code},'%') </if> <if test="query.phone != null and query.phone != ''"> and t3.phone like concat('%',#{query.phone},'%') </if> <if test="query.time != null and query.time != ''"> and t2.create_time between concat(substring(#{query.time}, 1, 10), ' 00:00:00') and concat(substring(#{query.time}, 14, 10), ' 23:59:59') </if> <if test="query.auditStatus != null"> and t1.status = #{query.auditStatus} </if> <if test="query.companyId != null"> and t2.company_id = #{query.companyId} </if> <if test="query.name != null and query.name != ''"> and t4.name like concat('%',#{query.name},'%') </if>