bug修改

This commit is contained in:
zengtao01
2024-07-24 14:21:38 +08:00
parent ee29e19d95
commit 82eb8b56ce
32 changed files with 996 additions and 32 deletions

View File

@ -91,11 +91,14 @@ public interface ErrorCodeConstants {
ErrorCode DEMO_TRANSFER_FAIL_PRICE_NOT_MATCH = new ErrorCode(1_007_901_003, "转账失败,转账单金额不匹配");
ErrorCode DIVIDE_NOT_EXISTS = new ErrorCode(1_007_902_001, "分账单不存在");
ErrorCode ORDER_NOT_COMPLETE = new ErrorCode(1_007_902_002, "还有订单尚未结算");
ErrorCode WX_ACCOUNT_NO = new ErrorCode(1_007_902_002, "微信充值金额已用完");
ErrorCode DIVIDE_COMPANY_NOT_EXISTS = new ErrorCode(1_007_903_001, "分账公司不存在");
ErrorCode DIVIDE_INFO_NOT_EXISTS = new ErrorCode(1_007_904_001, "分账明细不存在");
ErrorCode REFUND_RECORD_NOT_EXISTS = new ErrorCode(1_007_905_001, "退款记录不存在");
}

View File

@ -35,5 +35,8 @@ public class DivideSaveReqVO {
@Schema(description = "微信分账单号", example = "3065")
private String orderId;
/**
* 渠道用户编号
*/
private String channelUserId;
}

View File

@ -0,0 +1,95 @@
package cn.iocoder.yudao.module.pay.controller.admin.refundrecord;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo.*;
import cn.iocoder.yudao.module.pay.dal.dataobject.refundrecord.RefundRecordDO;
import cn.iocoder.yudao.module.pay.service.refundrecord.RefundRecordService;
@Tag(name = "管理后台 - 退款记录")
@RestController
@RequestMapping("/pay/refund-record")
@Validated
public class RefundRecordController {
@Resource
private RefundRecordService refundRecordService;
@PostMapping("/create")
@Operation(summary = "创建退款记录")
@PreAuthorize("@ss.hasPermission('pay:refund-record:create')")
public CommonResult<Long> createRefundRecord(@Valid @RequestBody RefundRecordSaveReqVO createReqVO) {
return success(refundRecordService.createRefundRecord(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新退款记录")
@PreAuthorize("@ss.hasPermission('pay:refund-record:update')")
public CommonResult<Boolean> updateRefundRecord(@Valid @RequestBody RefundRecordSaveReqVO updateReqVO) {
refundRecordService.updateRefundRecord(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除退款记录")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('pay:refund-record:delete')")
public CommonResult<Boolean> deleteRefundRecord(@RequestParam("id") Long id) {
refundRecordService.deleteRefundRecord(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得退款记录")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('pay:refund-record:query')")
public CommonResult<RefundRecordRespVO> getRefundRecord(@RequestParam("id") Long id) {
RefundRecordDO refundRecord = refundRecordService.getRefundRecord(id);
return success(BeanUtils.toBean(refundRecord, RefundRecordRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得退款记录分页")
@PreAuthorize("@ss.hasPermission('pay:refund-record:query')")
public CommonResult<PageResult<RefundRecordRespVO>> getRefundRecordPage(@Valid RefundRecordPageReqVO pageReqVO) {
PageResult<RefundRecordDO> pageResult = refundRecordService.getRefundRecordPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, RefundRecordRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出退款记录 Excel")
@PreAuthorize("@ss.hasPermission('pay:refund-record:export')")
@OperateLog(type = EXPORT)
public void exportRefundRecordExcel(@Valid RefundRecordPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<RefundRecordDO> list = refundRecordService.getRefundRecordPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "退款记录.xls", "数据", RefundRecordRespVO.class,
BeanUtils.toBean(list, RefundRecordRespVO.class));
}
}

View File

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 退款记录分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RefundRecordPageReqVO extends PageParam {
@Schema(description = "渠道编号", example = "13125")
private Long channelId;
@Schema(description = "渠道编码")
private String channelCode;
@Schema(description = "渠道用户编号", example = "19090")
private String channelUserId;
@Schema(description = "会员编号", example = "21945")
private String userId;
@Schema(description = "总金额,单位:分", example = "11049")
private Integer totalPrice;
@Schema(description = "退款状态", example = "1")
private String status;
@Schema(description = "商户订单号")
private String outTradeNo;
@Schema(description = "微信订单号", example = "26320")
private String transactionId;
@Schema(description = "微信退款单号")
private String outRefundNo;
@Schema(description = "微信支付退款单号", example = "8006")
private String refundId;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,64 @@
package cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 退款记录 Response VO")
@Data
@ExcelIgnoreUnannotated
public class RefundRecordRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "8454")
@ExcelProperty("主键")
private Long id;
@Schema(description = "渠道编号", example = "13125")
@ExcelProperty("渠道编号")
private Long channelId;
@Schema(description = "渠道编码")
@ExcelProperty("渠道编码")
private String channelCode;
@Schema(description = "渠道用户编号", example = "19090")
@ExcelProperty("渠道用户编号")
private String channelUserId;
@Schema(description = "会员编号", example = "21945")
@ExcelProperty("会员编号")
private String userId;
@Schema(description = "总金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "11049")
@ExcelProperty("总金额,单位:分")
private Integer totalPrice;
@Schema(description = "退款状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("退款状态")
private String status;
@Schema(description = "商户订单号")
@ExcelProperty("商户订单号")
private String outTradeNo;
@Schema(description = "微信订单号", example = "26320")
@ExcelProperty("微信订单号")
private String transactionId;
@Schema(description = "微信退款单号")
@ExcelProperty("微信退款单号")
private String outRefundNo;
@Schema(description = "微信支付退款单号", example = "8006")
@ExcelProperty("微信支付退款单号")
private String refundId;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 退款记录新增/修改 Request VO")
@Data
public class RefundRecordSaveReqVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "8454")
private Long id;
@Schema(description = "渠道编号", example = "13125")
private Long channelId;
@Schema(description = "渠道编码")
private String channelCode;
@Schema(description = "渠道用户编号", example = "19090")
private String channelUserId;
@Schema(description = "会员编号", example = "21945")
private String userId;
@Schema(description = "总金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "11049")
@NotNull(message = "总金额,单位:分不能为空")
private Integer totalPrice;
@Schema(description = "退款状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotEmpty(message = "退款状态不能为空")
private String status;
@Schema(description = "商户订单号")
private String outTradeNo;
@Schema(description = "微信订单号", example = "26320")
private String transactionId;
@Schema(description = "微信退款单号")
private String outRefundNo;
@Schema(description = "微信支付退款单号", example = "8006")
private String refundId;
}

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.pay.controller.app.divide;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.pay.controller.app.divide.vo.DrawMoneyVO;
import cn.iocoder.yudao.module.pay.service.divide.DivideService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 分账单")
@RestController
@RequestMapping("/pay/divide")
@Validated
public class AppDivideController {
@Resource
private DivideService divideService;
@PostMapping("/drawMoney")
@Operation(summary = "提现")
public CommonResult<Boolean> createDivide(@RequestBody DrawMoneyVO drawMoneyVO) {
return success(divideService.drawMoney(drawMoneyVO));
}
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.pay.controller.app.divide.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 分账单新增/修改 Request VO")
@Data
public class DrawMoneyVO {
@Schema(description = "用户编号")
private Long userId;
@Schema(description = "总金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "30938")
//@NotNull(message = "总金额,单位:分不能为空")
private Integer totalPrice;
/**
* 渠道用户编号
*/
private String channelUserId;
}

View File

@ -43,10 +43,31 @@ public class DivideDO extends BaseDO {
* 总金额,单位:分
*/
private Integer totalPrice;
/**
* 已分金额,单位:分
*/
private Integer cpPrice;
/**
* 渠道用户编号
*/
private String channelUserId;
/**
* 待分金额,单位:分
*/
private Integer unPrice;
/**
* 分账状态
*/
private String status;
/**
* 是否退款
*/
private String refundStatus;
/**
* 商户分账单号
*/
@ -60,4 +81,8 @@ public class DivideDO extends BaseDO {
*/
private String orderId;
/**
* 退款金额
*/
private Integer refundPrice;
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.pay.dal.dataobject.dividerecord;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* 分账记录 DO
*
* @author 管理员
*/
@TableName("pay_divide_record")
@KeySequence("pay_divide_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DivideRecordDO extends BaseDO {
/**
* 主键
*/
@TableId
private Long id;
/**
* 商户分账单号
*/
private String outOrderNo;
/**
* 微信订单号
*/
private String transactionId;
}

View File

@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.pay.dal.dataobject.refundrecord;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 退款记录 DO
*
* @author 管理员
*/
@TableName("pay_refund_record")
@KeySequence("pay_refund_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RefundRecordDO extends BaseDO {
/**
* 主键
*/
@TableId
private Long id;
/**
* 渠道编号
*/
private Long channelId;
/**
* 渠道编码
*/
private String channelCode;
/**
* 渠道用户编号
*/
private String channelUserId;
/**
* 会员编号
*/
private String userId;
/**
* 总金额,单位:分
*/
private Integer totalPrice;
/**
* 退款状态
*/
private String status;
/**
* 商户订单号
*/
private String outTradeNo;
/**
* 微信订单号
*/
private String transactionId;
/**
* 微信退款单号
*/
private String outRefundNo;
/**
* 微信支付退款单号
*/
private String refundId;
}

View File

@ -1,13 +1,14 @@
package cn.iocoder.yudao.module.pay.dal.mysql.divide;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.pay.controller.admin.divide.vo.DividePageReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.divide.DivideDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.pay.controller.admin.divide.vo.*;
import org.apache.ibatis.annotations.Select;
import java.math.BigDecimal;
/**
* 分账单 Mapper
@ -30,4 +31,17 @@ public interface DivideMapper extends BaseMapperX<DivideDO> {
.orderByDesc(DivideDO::getId));
}
@Select("select sum(total_money) from member_dish_order where DATE(create_time) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)")
BigDecimal getToday();
@Select("select wx_amount from member_card where user_id = #{userId} order by create_time desc limit 1")
BigDecimal getWxAmount(Long userId);
@Select("select count(1) from member_dish_order where user_id = #{userId} and order_status = '0'")
int orderCount(Long userId);
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.pay.dal.mysql.dividerecord;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.pay.dal.dataobject.dividerecord.DivideRecordDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 分账记录 Mapper
*
* @author 管理员
*/
@Mapper
public interface DivideRecordMapper extends BaseMapperX<DivideRecordDO> {
@Select("select * from pay_divide_record where DATE(create_time) = CURDATE()")
List<DivideRecordDO> getList();
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.pay.dal.mysql.refundrecord;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.pay.dal.dataobject.refundrecord.RefundRecordDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo.*;
/**
* 退款记录 Mapper
*
* @author 管理员
*/
@Mapper
public interface RefundRecordMapper extends BaseMapperX<RefundRecordDO> {
default PageResult<RefundRecordDO> selectPage(RefundRecordPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<RefundRecordDO>()
.eqIfPresent(RefundRecordDO::getChannelId, reqVO.getChannelId())
.eqIfPresent(RefundRecordDO::getChannelCode, reqVO.getChannelCode())
.eqIfPresent(RefundRecordDO::getChannelUserId, reqVO.getChannelUserId())
.eqIfPresent(RefundRecordDO::getUserId, reqVO.getUserId())
.eqIfPresent(RefundRecordDO::getTotalPrice, reqVO.getTotalPrice())
.eqIfPresent(RefundRecordDO::getStatus, reqVO.getStatus())
.eqIfPresent(RefundRecordDO::getOutTradeNo, reqVO.getOutTradeNo())
.eqIfPresent(RefundRecordDO::getTransactionId, reqVO.getTransactionId())
.eqIfPresent(RefundRecordDO::getOutRefundNo, reqVO.getOutRefundNo())
.eqIfPresent(RefundRecordDO::getRefundId, reqVO.getRefundId())
.betweenIfPresent(RefundRecordDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(RefundRecordDO::getId));
}
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.service.divide;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.divide.vo.DividePageReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.divide.vo.DivideSaveReqVO;
import cn.iocoder.yudao.module.pay.controller.app.divide.vo.DrawMoneyVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.divide.DivideDO;
import javax.validation.Valid;
@ -66,4 +67,10 @@ public interface DivideService {
* 解冻剩余资金
*/
int getDivideFreeze();
/**
* 解冻剩余资金
*/
Boolean drawMoney( DrawMoneyVO drawMoneyVO);
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.divide;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
@ -10,10 +11,15 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto
import cn.iocoder.yudao.framework.pay.core.enums.divide.PayDivideStatusRespEnum;
import cn.iocoder.yudao.module.pay.controller.admin.divide.vo.DividePageReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.divide.vo.DivideSaveReqVO;
import cn.iocoder.yudao.module.pay.controller.app.divide.vo.DrawMoneyVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.divide.DivideDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.dividecompany.DivideCompanyDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.divideinfo.DivideInfoDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.dividerecord.DivideRecordDO;
import cn.iocoder.yudao.module.pay.dal.mysql.divide.DivideMapper;
import cn.iocoder.yudao.module.pay.dal.mysql.dividerecord.DivideRecordMapper;
import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
import cn.iocoder.yudao.module.pay.service.dividecompany.DivideCompanyService;
import cn.iocoder.yudao.module.pay.service.divideinfo.DivideInfoService;
@ -24,12 +30,16 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.DIVIDE_NOT_EXISTS;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
/**
* 分账单 Service 实现类
@ -52,6 +62,16 @@ public class DivideServiceImpl implements DivideService {
@Resource
private PayChannelService channelService;
@Resource
private PayNoRedisDAO noRedisDAO;
@Resource
private PayProperties payProperties;
@Resource
private DivideRecordMapper divideRecordMapper;
@Override
public Long createDivide(DivideSaveReqVO createReqVO) {
// 插入
@ -105,7 +125,7 @@ public class DivideServiceImpl implements DivideService {
for (DivideCompanyDO divideCompanyDO : companyList) {
DivideInfoDO divideInfoDO = new DivideInfoDO();
int money = (int) Math.ceil(divideDO.getTotalPrice() * Double.valueOf(divideCompanyDO.getProportion()));
int money = (int) Math.ceil(divideDO.getUnPrice() * Double.valueOf(divideCompanyDO.getProportion()));
divideInfoDO.setTransactionId(divideDO.getChannelOrderNo())
.setOutOrderNo(divideDO.getNo())
.setName(divideCompanyDO.getName())
@ -128,14 +148,48 @@ public class DivideServiceImpl implements DivideService {
@Override
public int startDivide() {
List<DivideDO> divideDOS = divideMapper.selectList(Wrappers.<DivideDO>lambdaQuery()
.eq(DivideDO::getStatus, PayDivideStatusRespEnum.WAITING.getStatus()));
BigDecimal today = divideMapper.getToday();
int money = today.multiply(new BigDecimal("100")).intValue();
LocalDateTime now = LocalDateTime.now();
LocalDateTime thirtyDaysAgo = now.minusDays(30);
List<DivideDO> divideDOS = divideMapper.selectList(Wrappers.<DivideDO>lambdaQuery()
.eq(DivideDO::getStatus, PayDivideStatusRespEnum.WAITING.getStatus())
.ge(DivideDO::getCreateTime,thirtyDaysAgo)
.orderByAsc(DivideDO::getCreateTime));
if(CollectionUtil.isEmpty(divideDOS)){
return 0;
}
List<DivideDO> divideList = new ArrayList<>();
int sum = 0;
for(DivideDO divideDO: divideDOS){
Integer totalPrice = divideDO.getTotalPrice()-divideDO.getCpPrice();
sum = sum+totalPrice;
if(sum<money){
divideDO.setUnPrice(totalPrice);
divideDO.setCpPrice(divideDO.getCpPrice()+totalPrice);
divideList.add(divideDO);
} else if (sum ==money) {
divideDO.setUnPrice(totalPrice);
divideDO.setCpPrice(divideDO.getCpPrice()+totalPrice);
divideList.add(divideDO);
break;
}else {
int leftMoney = money+totalPrice- sum;
divideDO.setUnPrice(leftMoney);
divideDO.setCpPrice(divideDO.getCpPrice()+leftMoney);
divideList.add(divideDO);
break;
}
}
List<DivideRecordDO> divideRecordDOList = new ArrayList<>();
int counter = 0;
for (DivideDO divideDO : divideDOS) {
for (DivideDO divideDO : divideList) {
PayClient client = channelService.getPayClient(divideDO.getChannelId());
PayDivideUnifiedDto payDivideUnifiedDto = new PayDivideUnifiedDto();
@ -143,8 +197,19 @@ public class DivideServiceImpl implements DivideService {
.setOutOrderNo(divideDO.getNo())
.setUnfreezeUnsplit(false)
.setReceivers(createDivideInfo(divideDO));
if(divideDO.getTotalPrice().equals(divideDO.getCpPrice())) {
payDivideUnifiedDto.setUnfreezeUnsplit(true);
divideDO.setStatus(PayDivideStatusRespEnum.PROGRESS.getStatus());
}
PayDivideRespDto payDivideRespDto = client.unifiedDivide(payDivideUnifiedDto);
divideDO.setStatus(PayDivideStatusRespEnum.PROGRESS.getStatus());
DivideRecordDO divideRecordDO = new DivideRecordDO();
divideRecordDO.setTransactionId(divideDO.getChannelOrderNo())
.setOutOrderNo(divideDO.getNo());
divideRecordDOList.add(divideRecordDO);
divideDO.setOrderId(payDivideRespDto.getOrderId());
// 每执行250次休息一分钟
@ -158,14 +223,26 @@ public class DivideServiceImpl implements DivideService {
}
}
divideMapper.updateBatch(divideDOS);
divideRecordMapper.insertBatch(divideRecordDOList);
return divideDOS.size();
}
@Override
public int getDivideResult() {
List<DivideRecordDO> divideRecordDOList = divideRecordMapper.getList();
if(CollectionUtil.isEmpty(divideRecordDOList)){
return 0;
}
Stream<String> transactionIdList = divideRecordDOList.stream().map(DivideRecordDO::getTransactionId);
Stream<String> OutOrderNoList = divideRecordDOList.stream().map(DivideRecordDO::getOutOrderNo);
List<DivideDO> divideDOS = divideMapper.selectList(Wrappers.<DivideDO>lambdaQuery()
.eq(DivideDO::getStatus, PayDivideStatusRespEnum.PROGRESS.getStatus()));
.in(DivideDO::getChannelOrderNo, transactionIdList)
.in(DivideDO::getNo,OutOrderNoList));
if(CollectionUtil.isEmpty(divideDOS)){
return 0;
}
@ -178,7 +255,12 @@ public class DivideServiceImpl implements DivideService {
.setOutOrderNo(divideDO.getNo());
PayDivideRespDto payDivideRespDto = client.unifiedDivideResult(payDivideUnifiedDto);
updateDivideInfo(payDivideRespDto.getReceivers(),divideDO.getNo());
divideDO.setStatus(PayDivideStatusRespEnum.COMPLETE.getStatus());
if(divideDO.getTotalPrice().equals(divideDO.getCpPrice())) {
divideDO.setStatus(PayDivideStatusRespEnum.COMPLETE.getStatus());
}else{
divideDO.setNo(noRedisDAO.generate(payProperties.getOrderNoPrefix()));
}
}
divideMapper.updateBatch(divideDOS);
return divideDOS.size();
@ -230,5 +312,95 @@ public class DivideServiceImpl implements DivideService {
return true;
}
@Override
public Boolean drawMoney(DrawMoneyVO drawMoneyVO) {
//判断订单是否完成
int i = divideMapper.orderCount(drawMoneyVO.getUserId());
if(i>0){
throw new ServiceException(ORDER_NOT_COMPLETE);
}
//判断是否有金额可退款
BigDecimal wxAmount = divideMapper.getWxAmount(drawMoneyVO.getUserId());
int money = wxAmount.multiply(new BigDecimal("100")).intValue();
if(money<=0){
throw new ServiceException(WX_ACCOUNT_NO);
}
//查询最近的充值订单,时间倒序退款
List<DivideDO> divideDOS = divideMapper.selectList(Wrappers.<DivideDO>lambdaQuery()
.eq(DivideDO::getChannelUserId, drawMoneyVO.getChannelUserId())
.eq(DivideDO::getRefundStatus,"0")
.orderByDesc(DivideDO::getCreateTime));
//筛选出未分账的订单
List<DivideDO> unDivideList = divideDOS.stream().filter(vo -> vo.getCpPrice() == 0).collect(Collectors.toList());
//筛选出已分账的订单
List<DivideDO> divideList = divideDOS.stream().filter(vo -> vo.getCpPrice().equals(vo.getTotalPrice())).collect(Collectors.toList());
//剩下的是未分账完 的订单
divideDOS.removeAll(unDivideList);
divideDOS.removeAll(divideList);
//需要回退的订单
List<DivideDO> backList = new ArrayList<>();
//不需要回退的订单
List<DivideDO> noBackList = new ArrayList<>();
int sum = 0;
//先从未分账的订单计算
for (DivideDO divideDO: unDivideList){
Integer totalPrice = divideDO.getTotalPrice()-divideDO.getCpPrice();
sum = sum+totalPrice;
if(sum<=money){
divideDO.setRefundPrice(totalPrice);
divideDO.setCpPrice(divideDO.getCpPrice()+totalPrice);
noBackList.add(divideDO);
}else {
int leftMoney = money+totalPrice- sum;
divideDO.setRefundPrice(leftMoney);
divideDO.setCpPrice(divideDO.getCpPrice()+leftMoney);
noBackList.add(divideDO);
break;
}
}
//从分账完的订单进行退款
if(sum<money){
for (DivideDO divideDO:divideList){
Integer totalPrice = divideDO.getTotalPrice()-divideDO.getCpPrice();
sum = sum+totalPrice;
if(sum<=money){
divideDO.setRefundPrice(totalPrice);
backList.add(divideDO);
}else {
int leftMoney = money+totalPrice- sum;
divideDO.setRefundPrice(leftMoney);
backList.add(divideDO);
break;
}
}
}
return null;
}
}

View File

@ -305,7 +305,8 @@ public class PayOrderServiceImpl implements PayOrderService {
.setChannelCode(channel.getCode())
.setTotalPrice(payOrderDO.getPrice())
.setNo(no).setStatus(PayDivideStatusRespEnum.WAITING.getStatus())
.setChannelOrderNo(payOrderDO.getChannelOrderNo());
.setChannelOrderNo(payOrderDO.getChannelOrderNo())
.setChannelUserId(payOrderDO.getChannelUserId());
divideService.createDivide(divideSaveReqVO);
}

View File

@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.pay.service.refundrecord;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo.RefundRecordPageReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo.RefundRecordSaveReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.refundrecord.RefundRecordDO;
import javax.validation.Valid;
/**
* 退款记录 Service 接口
*
* @author 管理员
*/
public interface RefundRecordService {
/**
* 创建退款记录
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createRefundRecord(@Valid RefundRecordSaveReqVO createReqVO);
/**
* 更新退款记录
*
* @param updateReqVO 更新信息
*/
void updateRefundRecord(@Valid RefundRecordSaveReqVO updateReqVO);
/**
* 删除退款记录
*
* @param id 编号
*/
void deleteRefundRecord(Long id);
/**
* 获得退款记录
*
* @param id 编号
* @return 退款记录
*/
RefundRecordDO getRefundRecord(Long id);
/**
* 获得退款记录分页
*
* @param pageReqVO 分页查询
* @return 退款记录分页
*/
PageResult<RefundRecordDO> getRefundRecordPage(RefundRecordPageReqVO pageReqVO);
}

View File

@ -0,0 +1,74 @@
package cn.iocoder.yudao.module.pay.service.refundrecord;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo.*;
import cn.iocoder.yudao.module.pay.dal.dataobject.refundrecord.RefundRecordDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.pay.dal.mysql.refundrecord.RefundRecordMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
/**
* 退款记录 Service 实现类
*
* @author 管理员
*/
@Service
@Validated
public class RefundRecordServiceImpl implements RefundRecordService {
@Resource
private RefundRecordMapper refundRecordMapper;
@Override
public Long createRefundRecord(RefundRecordSaveReqVO createReqVO) {
// 插入
RefundRecordDO refundRecord = BeanUtils.toBean(createReqVO, RefundRecordDO.class);
refundRecordMapper.insert(refundRecord);
// 返回
return refundRecord.getId();
}
@Override
public void updateRefundRecord(RefundRecordSaveReqVO updateReqVO) {
// 校验存在
validateRefundRecordExists(updateReqVO.getId());
// 更新
RefundRecordDO updateObj = BeanUtils.toBean(updateReqVO, RefundRecordDO.class);
refundRecordMapper.updateById(updateObj);
}
@Override
public void deleteRefundRecord(Long id) {
// 校验存在
validateRefundRecordExists(id);
// 删除
refundRecordMapper.deleteById(id);
}
private void validateRefundRecordExists(Long id) {
if (refundRecordMapper.selectById(id) == null) {
throw exception(REFUND_RECORD_NOT_EXISTS);
}
}
@Override
public RefundRecordDO getRefundRecord(Long id) {
return refundRecordMapper.selectById(id);
}
@Override
public PageResult<RefundRecordDO> getRefundRecordPage(RefundRecordPageReqVO pageReqVO) {
return refundRecordMapper.selectPage(pageReqVO);
}
}