资金管理移除充值相关内容、新增优惠活动相关接口、软件购买增加对应产品的优惠活动赠送时间

This commit is contained in:
gaoqr
2025-11-04 14:19:50 +08:00
parent f66a96a468
commit 44ddf171c9
79 changed files with 1031 additions and 4060 deletions
@@ -53,6 +53,12 @@ public class AssertUtils {
}
}
public static void empty(Object object, ErrorCode errorCode, Object... params) {
if (object != null) {
throw ServiceExceptionUtil.exception(errorCode, params);
}
}
public static void notEmpty(Object object, ErrorCode errorCode) {
if (object == null) {
throw exception(errorCode);
@@ -415,39 +415,27 @@ public class ErrorCodeConstants {
public static final ErrorCode ORGAN_AMOUNT_NO_EXIST = new ErrorCode(1_002_043_001, "当前组织没有可用的资金记录,请联系客服");
public static final ErrorCode INVOICE_NO_EXIST = new ErrorCode(1_002_043_002, "当前发票记录有误,请重新查看");
public static final ErrorCode INVOICING_REJECT_REASON = new ErrorCode(1_002_043_003, "请填写拒绝开票原因");
public static final ErrorCode INVOICE_FILE_IS_NULL = new ErrorCode(1_002_043_004, "发票附件不存在,请重新上传");
public static final ErrorCode INVOICE_FILE_UPLOAD_FAILED = new ErrorCode(1_002_043_005, "发票附件上传失败,请重新上传");
public static final ErrorCode INVOICE_FILE_IS_NULL_NOT_DOWNLOAD = new ErrorCode(1_002_043_006, "发票附件不存在,无法下载");
public static final ErrorCode INVOICE_FILE_DATA_ERROR = new ErrorCode(1_002_043_007, "发票附件下载失败,请重新下载或稍等重试");
public static final ErrorCode PURCHASE_RECORD_NO_EXIST = new ErrorCode(1_002_043_008, "当前发票对应的购买记录有误,请退回组织后重新申请开票");
public static final ErrorCode INVOICE_TITLE_NO_EXIST = new ErrorCode(1_002_043_009, "发票抬头信息有误,请进行查看");
public static final ErrorCode THIS_INVOICE_IS_FAIL = new ErrorCode(1_002_043_010, "当前发票已开票,无法再次进行开票");
public static final ErrorCode THIS_INVOICE_IS_SUCCESS = new ErrorCode(1_002_043_011, "当前发票已经开票,无法再次进行开票");
public static final ErrorCode PRODUCTS_IS_EXIST = new ErrorCode(1_002_043_012, "产品【{}】已存在,请修改产品名称后再次操作");
public static final ErrorCode PRODUCTS_NO_DELETE = new ErrorCode(1_002_043_013, "当前产品已上架,无法删除,请下架后再删除");
public static final ErrorCode PRODUCTS_NO_UPDATE = new ErrorCode(1_002_043_014, "当前产品已上架,无法进行修改");
public static final ErrorCode PRODUCTS_DETAIL_NO_UPDATE = new ErrorCode(1_002_043_016, "定价规则对应的产品已上架,无法进行修改");
public static final ErrorCode ADVERTISEMENT_START_TIME_ERROR = new ErrorCode(1_002_043_017, "投放时间错误,开始时间应等于或大于当日");
public static final ErrorCode ADVERTISEMENT_TIME_ERROR = new ErrorCode(1_002_043_018, "投放时间错误,结束时间应大于开始时间");
public static final ErrorCode ADVERTISEMENT_NAME_IS_EXIST = new ErrorCode(1_002_043_019, "当前广告名称已存在,请重新命名");
public static final ErrorCode ADVERTISEMENT_NO_DELETE = new ErrorCode(1_002_043_020, "当前广告已经发布,无法删除,请结束发布后再删除");
public static final ErrorCode ADVERTISEMENT_REPUBLISH_NO_TIME = new ErrorCode(1_002_043_021, "广告重新发布,应重新选择投放时间");
public static final ErrorCode RECHARGE_ACTIVE_NAME_IS_EXIST = new ErrorCode(1_002_043_022, "当前赠送金活动名称已存在,请修改");
public static final ErrorCode IMAGE_UPLOAD_ERROR = new ErrorCode(1_002_043_023, "图片上传失败,请重试或重新选择图片");
public static final ErrorCode ORGAN_RECHARGE_AMOUNT_UPDATE_ERROR = new ErrorCode(1_002_043_024, "组织充值失败,请检查组织资金数据");
public static final ErrorCode ORGAN_PRODUCT_PAY_AMOUNT_CHANGE_ERROR = new ErrorCode(1_002_043_025, "发起产品支付失败,组织资金已发生改变,请刷新或稍后再发起支付");
public static final ErrorCode PAY_RECHARGE_ACTIVITY_CHANNEL_MISMATCH_ERROR = new ErrorCode(1_002_043_026, "充值活动类型和支付渠道不匹配,请选择其他充值活动!");
public static final ErrorCode PAY_RECHARGE_ACTIVITY_EXPIRE_ERROR = new ErrorCode(1_002_043_027, "充值活动已结束,请选择其他充值活动!");
public static final ErrorCode INVOICE_TITLE_NOT_EXISTS_ERROR = new ErrorCode(1_002_043_028, "发票抬头不存在,请先创建发票抬头");
public static final ErrorCode ORG_INVOICE_PURCHASE_RECORD_UPDATE_NUM_NOT_MATCH_ERROR = new ErrorCode(1_002_043_029, "当前勾选的购买记录中部分可能已开票,请查询后重新勾选提交开票");
public static final ErrorCode ORG_INVOICE_AGREE_FILE_NULL_ERROR = new ErrorCode(1_002_043_030, "确认开票发票附件不能为空,请上传后再提交");
public static final ErrorCode INVOICE_TITLE_ORG_EXISTS_ERROR = new ErrorCode(1_002_043_031, "组织下已存在发票抬头,请刷新后编辑抬头内容");
public static final ErrorCode INVOICE_TITLE_TAXPAYERID_EXISTS_ERROR = new ErrorCode(1_002_043_032, "统一社会信用代码已存在,请检查");
public static final ErrorCode PRODUCTS_NOT_NOLIST = new ErrorCode(1_002_043_033, "当前产品未上架");
public static final ErrorCode ORG_PRODUCT_PURCHASE_LOCK_ERROR = new ErrorCode(1_002_043_034, "组织下存在购买中的产品操作,请稍后再试");
public static final ErrorCode INVOICE_TITLE_ENTERPRISE_TAXNUMBER_EMPTY_ERROR = new ErrorCode(1_002_043_035, "企业统一信用代码不能为空");
public static final ErrorCode INVOICE_AMOUNT_ZERO_ERROR = new ErrorCode(1_002_043_036, "可开票金额为,请检查购买记录");
public static final ErrorCode INVOICE_APPLY_UNINVOICEABLE_EXIST = new ErrorCode(1_002_043_036, "当前提交记录中存在不可开票记录,请刷新列表后重新选择提交");
public static final ErrorCode PURCHASE_RECORD_NO_EXIST = new ErrorCode(1_002_043_004, "当前发票对应的购买记录有误,请退回组织后重新申请开票");
public static final ErrorCode THIS_INVOICE_IS_FAIL = new ErrorCode(1_002_043_005, "当前发票已开票,无法再次进行开票");
public static final ErrorCode PRODUCTS_IS_EXIST = new ErrorCode(1_002_043_006, "产品【{}】已存在,请修改产品名称后再次操作");
public static final ErrorCode PRODUCTS_NO_DELETE = new ErrorCode(1_002_043_007, "当前产品已上架,无法删除,请下架后再删除");
public static final ErrorCode PRODUCTS_NO_UPDATE = new ErrorCode(1_002_043_008, "当前产品已上架,无法进行修改");
public static final ErrorCode PRODUCTS_DETAIL_NO_UPDATE = new ErrorCode(1_002_043_009, "定价规则对应的产品已上架,无法进行修改");
public static final ErrorCode ADVERTISEMENT_TIME_ERROR = new ErrorCode(1_002_043_010, "投放时间错误,结束时间应大于开始时间");
public static final ErrorCode ADVERTISEMENT_NAME_IS_EXIST = new ErrorCode(1_002_043_011, "当前广告名称已存在,请重新命名");
public static final ErrorCode ADVERTISEMENT_NO_DELETE = new ErrorCode(1_002_043_012, "当前广告已经发布,无法删除,请结束发布后再删除");
public static final ErrorCode PRODUCT_PROMOTION_ACTIVE_NAME_IS_EXIST = new ErrorCode(1_002_043_013, "当前优惠活动名称已存在,请修改");
public static final ErrorCode PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST = new ErrorCode(1_002_043_014, "当前所选产品下{}{}购买时长的优惠活动已存在,请修改");
public static final ErrorCode INVOICE_TITLE_NOT_EXISTS_ERROR = new ErrorCode(1_002_043_017, "发票抬头不存在,请先创建发票抬头");
public static final ErrorCode ORG_INVOICE_PURCHASE_RECORD_UPDATE_NUM_NOT_MATCH_ERROR = new ErrorCode(1_002_043_018, "当前勾选的购买记录中部分可能已开票,请查询后重新勾选提交开票");
public static final ErrorCode ORG_INVOICE_AGREE_FILE_NULL_ERROR = new ErrorCode(1_002_043_019, "确认开票发票附件不能为空,请上传后再提交");
public static final ErrorCode INVOICE_TITLE_ORG_EXISTS_ERROR = new ErrorCode(1_002_043_020, "组织下已存在发票抬头,请刷新后编辑抬头内容");
public static final ErrorCode INVOICE_TITLE_TAXPAYERID_EXISTS_ERROR = new ErrorCode(1_002_043_021, "统一社会信用代码已存在,请检查");
public static final ErrorCode PRODUCTS_NOT_NOLIST = new ErrorCode(1_002_043_022, "当前产品未上架");
public static final ErrorCode ORG_PRODUCT_PURCHASE_LOCK_ERROR = new ErrorCode(1_002_043_023, "组织下存在购买中的产品操作,请稍后再试");
public static final ErrorCode INVOICE_TITLE_ENTERPRISE_TAXNUMBER_EMPTY_ERROR = new ErrorCode(1_002_043_024, "企业统一信用代码不能为空");
public static final ErrorCode INVOICE_AMOUNT_ZERO_ERROR = new ErrorCode(1_002_043_025, "可开票金额为,请检查购买记录");
public static final ErrorCode INVOICE_APPLY_UNINVOICEABLE_EXIST = new ErrorCode(1_002_043_026, "当前提交记录中存在不可开票记录,请刷新列表后重新选择提交");
//=========== 支付相关 1-002-048-000 ============
public static final ErrorCode PAY_CHANNEL_NOT_SUPPORT = new ErrorCode(1_002_048_000, "暂不支持的支付渠道,请使用其他支付渠道");
@@ -456,39 +444,25 @@ public class ErrorCodeConstants {
public static final ErrorCode PAY_ORDER_NOTIFY_DATA_PARSE_ERROR = new ErrorCode(1_002_048_003, "解析支付回调数据异常");
public static final ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1_002_048_004, "支付订单不处于待支付");
public static final ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_002_048_005, "发起渠道支付异常,请联系客服");
public static final ErrorCode PAY_RECHARGE_ORDER_ORGANID_CHECK_ERROR = new ErrorCode(1_002_048_006, "充值目标组织和当前操作人组织不同,发起充值支付失败");
public static final ErrorCode PAY_RECHARGE_LOCK_EXISTS_ERROR = new ErrorCode(1_002_048_007, "组织下存在待支付的充值订单,请稍后再试");
public static final ErrorCode PAY_NOTIFY_PASSBACK_NOT_EXISTS_ERROR = new ErrorCode(1_002_048_008, "支付回调缺少passback_params,请检查支付渠道");
public static final ErrorCode PAY_NOTIFY_PASSBACK_TRADETYPE_NOT_SUPPORT_ERROR = new ErrorCode(1_002_048_009, "不支持的支付回调tradeType:【{}】,请检查支付渠道");
public static final ErrorCode PAY_PRODUCT_BALANCE_INSUFFICIENT = new ErrorCode(1_002_048_010, "现金余额不足,请选择其他支付方式!");
public static final ErrorCode PAY_PRODUCT_GIFT_BALANCE_INSUFFICIENT = new ErrorCode(1_002_048_011, "赠送金余额不足,请选择其他支付方式!");
public static final ErrorCode PAY_PRODUCT_AVAILABLE_BALANCE_INSUFFICIENT = new ErrorCode(1_002_048_012, "可用金(现金余额+赠送金)余额不足,请选择其他支付方式!");
public static final ErrorCode PAY_NOTIFY_PASSBACK_TRADETYPE_NOT_SUPPORT_ERROR = new ErrorCode(1_002_048_006, "不支持的支付回调tradeType:【{}】,请检查支付渠道");
//=========== 产品相关 1-002-045-000 ============
public static final ErrorCode PRODUCTS_NO_EXIST = new ErrorCode(1_002_045_001, "当前产品不存在");
public static final ErrorCode PRODUCTS_DETAIL_NO_EXIST = new ErrorCode(1_002_045_002, "当前产品的规则不存在");
public static final ErrorCode PRODUCTS_DURATION_NOT_NULL = new ErrorCode(1_002_045_003, "当前购买方式为【时长】,请填写产品时长");
public static final ErrorCode PRODUCTS_OUTPUT_NOT_NULL = new ErrorCode(1_002_045_004, "购买方式为产量时,需确定产量数量");
public static final ErrorCode PRODUCTS_DETAIL_DURATION_EXIST = new ErrorCode(1_002_045_005, "当前产品下已存在产品时长:{}/{}的定价规则,请修改后重新操作");
public static final ErrorCode PRODUCTS_DETAIL_OUTPUT_EXIST = new ErrorCode(1_002_045_006, "存在当前产量的产品定价规则");
public static final ErrorCode PRODUCTS_DETAIL_CURRENTPRICE_CALCULATE_ERROR = new ErrorCode(1_002_045_007, "产品现价计算错误,期望价格【{}】");
public static final ErrorCode PRODUCTS_DURATION_INT_ERR = new ErrorCode(1_002_045_008, "产品定价规则:时长必须为整数且大于 0");
public static final ErrorCode PRODUCTS_OUTPUT_NOT_SUPPORT = new ErrorCode(1_002_045_009, "暂不支持创建购买方式为【产量】的定价规则");
public static final ErrorCode RECHARGE_ACTIVE_NO_EXIST = new ErrorCode(1_002_045_010, "当前赠送金活动不存在");
public static final ErrorCode PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT = new ErrorCode(1_002_045_011, "不支持的时长单位,请检查该定价规则的时长单位");
public static final ErrorCode ORG_PRODUCT_PURCHASE_WAIT_PAY_ERROR = new ErrorCode(1_002_045_012, "组织下存在当前产品的待支付记录,请确认或取消支付后再次发起软件购买");
public static final ErrorCode PRODUCT_PRICE_NULL_ERROR = new ErrorCode(1_002_045_013, "产品建议价格为空,请联系客服");
public static final ErrorCode ORG_PRODUCT_PURCHASE_NOT_EXIST_ERROR = new ErrorCode(1_002_045_014, "组织订购记录不存在,请检查数据");
public static final ErrorCode ORG_PRODUCT_PURCHASE_EXIST_ERROR = new ErrorCode(1_002_045_014, "组织[{}]订购记录已存在,请勿重复定义订购机构");
public static final ErrorCode PRODUCTS_DETAIL_DURATION_EXIST = new ErrorCode(1_002_045_003, "当前产品下已存在产品时长:{}/{}的定价规则,请修改后重新操作");
public static final ErrorCode PRODUCT_PROMOTION_NO_EXIST = new ErrorCode(1_002_045_004, "当前优惠活动不存在");
public static final ErrorCode PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT = new ErrorCode(1_002_045_005, "不支持的时长单位,请检查该定价规则的时长单位");
public static final ErrorCode ORG_PRODUCT_PURCHASE_WAIT_PAY_ERROR = new ErrorCode(1_002_045_006, "组织下存在当前产品的待支付记录,请确认或取消支付后再次发起软件购买");
public static final ErrorCode PRODUCT_PRICE_NULL_ERROR = new ErrorCode(1_002_045_007, "产品建议价格为空,请联系客服");
public static final ErrorCode ORG_PRODUCT_PURCHASE_NOT_EXIST_ERROR = new ErrorCode(1_002_045_008, "组织订购记录不存在,请检查数据");
public static final ErrorCode ORG_PRODUCT_PURCHASE_EXIST_ERROR = new ErrorCode(1_002_045_009, "组织[{}]订购记录已存在,请勿重复定义订购机构");
//=========== 广告相关 1-002-046-000 ============
public static final ErrorCode ADVERTISEMENT_POSITION_NO_EXIST = new ErrorCode(1_002_046_001, "广告所选放置位置不存在");
public static final ErrorCode ADVERTISEMENT_NO_EXIST = new ErrorCode(1_002_046_002, "广告不存在");
public static final ErrorCode ADVERTISEMENT_STATUS_ENDTIME_EXPIRED = new ErrorCode(1_002_046_003, "当前广告投放结束时间已超期,请重新发布选择投放时间或重新编辑投放时间");
public static final ErrorCode ADVERTISEMENT_FAIL = new ErrorCode(1_002_046_004, "自动发布失败");
public static final ErrorCode ADVERTISEMENT_IMAGE_EMPTY_ERROR = new ErrorCode(1_002_046_005, "广告图片文件为空,请重新上传");
public static final ErrorCode ADVERTISEMENT_IMAGE_UPLOAD_FAIL = new ErrorCode(1_002_046_006, "广告图片上传失败,请稍后再试");
public static final ErrorCode ADVERTISEMENT_UPDATE_STATUS_ERROR = new ErrorCode(1_002_046_007, "当前广告已经发布,若要编辑请先结束发布");
public static final ErrorCode ADVERTISEMENT_NO_EXIST = new ErrorCode(1_002_046_001, "广告不存在");
public static final ErrorCode ADVERTISEMENT_STATUS_ENDTIME_EXPIRED = new ErrorCode(1_002_046_002, "当前广告投放结束时间已超期,请重新发布选择投放时间或重新编辑投放时间");
public static final ErrorCode ADVERTISEMENT_IMAGE_EMPTY_ERROR = new ErrorCode(1_002_046_003, "广告图片文件为空,请重新上传");
public static final ErrorCode ADVERTISEMENT_IMAGE_UPLOAD_FAIL = new ErrorCode(1_002_046_004, "广告图片上传失败,请稍后再试");
public static final ErrorCode ADVERTISEMENT_UPDATE_STATUS_ERROR = new ErrorCode(1_002_046_005, "当前广告已经发布,若要编辑请先结束发布");
//=========== 解析器管理 1-002-044-000 ============
@@ -498,9 +472,4 @@ public class ErrorCodeConstants {
//=========== 产品延期管理 1-002-049-000 ============
public static final ErrorCode PRODUCT_PURCHASE_NO_EXIST = new ErrorCode(1_002_049_001, "当前购买记录不存在,请检查");
public static final ErrorCode PRODUCT_PURCHASE_ENDTIME_BEFORE_DELAYTIME_ERROR = new ErrorCode(1_002_049_002, "当前产品订购有效期{}未超过当前日期,请调整订购时长");
//=========== 手工调账管理 1-002-050-000 ============
public static final ErrorCode RECHARGE_GIFT_MEANWHILE_EMPTY_ERROR = new ErrorCode(1_002_050_001, "充值金额、赠送金额不能同时为空");
public static final ErrorCode ORGAMOUNT_RECHARGE_INSUFFICIENT_ERROR = new ErrorCode(1_002_050_002, "调减账户余额不足,请确保组织余额充足后重新操作");
public static final ErrorCode ORGAMOUNT_GIFT_INSUFFICIENT_ERROR = new ErrorCode(1_002_050_003, "调减账户赠送金余额不足,请确保组织赠送金余额充足后重新操作");
}
@@ -1,67 +0,0 @@
package com.cf.imes.module.system.enums.recharge;
import com.cf.imes.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 充值赠送类型枚举
*
* @author 晨丰科技
*/
@Getter
@AllArgsConstructor
public enum RechargeGiftTypeEnum implements IntArrayValuable {
FULL_X_GIVE_X(0, "满X送X"),
EVERY_X_GIVE_X(1, "每满X送X");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(RechargeGiftTypeEnum::getStatus).toArray();
/**
* 状态值
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
/**
* 是否满X送X
*
* @param name
* @return
*/
public static boolean isFullGive(String name) {
return Objects.equals(FULL_X_GIVE_X.name, name);
}
/**
* 是否每满X送X
*
* @param name
* @return
*/
public static boolean isEveryGive(String name) {
return Objects.equals(EVERY_X_GIVE_X.name, name);
}
public static RechargeGiftTypeEnum fromStatus(Integer status) {
for (RechargeGiftTypeEnum value : values()) {
if (Objects.equals(value.status, status)) {
return value;
}
}
return null;
}
}
@@ -1,62 +0,0 @@
package com.cf.imes.module.system.enums.recharge;
import com.cf.imes.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 充值类型枚举
*
* @author 晨丰科技
*/
@Getter
@AllArgsConstructor
public enum RechargeTypeEnum implements IntArrayValuable {
WECHAT_AND_ALIPAY(0, "微信、支付宝"),
WECHAT(1, "微信"),
ALIPAY(2, "支付宝");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(RechargeTypeEnum::getStatus).toArray();
/**
* 状态值
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
public static boolean isWechatAndAlipay(String name) {
return Objects.equals(WECHAT_AND_ALIPAY.name, name);
}
public static boolean isWechat(String name) {
return Objects.equals(WECHAT.name, name);
}
public static boolean isAlipay(String name) {
return Objects.equals(ALIPAY.name, name);
}
public static boolean isWechatAndAlipay(Integer status) {
return Objects.equals(WECHAT_AND_ALIPAY.status, status);
}
public static boolean isWechat(Integer status) {
return Objects.equals(WECHAT.status, status);
}
public static boolean isAlipay(Integer status) {
return Objects.equals(ALIPAY.status, status);
}
}
@@ -1,70 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.balancedetails;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.excel.core.util.ExcelUtils;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.controller.admin.funds.balancedetails.vo.BalanceDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.balancedetails.vo.BalanceDetailsRespVO;
import com.cf.imes.module.system.service.funds.incomeandexpense.IncomeExpenseService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
/**
* @author 组织余额明细
*/
@Tag(name = "管理后台 - 组织账户明细")
@RestController
@RequestMapping("/system/balance")
@Validated
public class BalanceDetailsController {
@Resource
private IncomeExpenseService incomeExpenseService;
@GetMapping("")
@Operation(summary = "查询组织账户明细分页")
public CommonResult<PageResult<BalanceDetailsRespVO>> getBalanceDetailsPage(@Valid BalanceDetailsPageReqVO pageReqVO) {
// 非管理端只能查看本组织数据
boolean manageEndPoint = SecurityFrameworkUtils.isManageEndPoint();
if (!manageEndPoint) {
pageReqVO.setOrganId(SecurityFrameworkUtils.getUserOrganId());
}
return success(incomeExpenseService.getBalanceDetailsPage(pageReqVO));
}
@GetMapping("/export")
@Operation(summary = "组织账户明细导出")
@OperateLog(type = EXPORT)
public void balanceDetailsExport(@Valid BalanceDetailsPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
// 非管理端只能查看本组织数据
boolean manageEndPoint = SecurityFrameworkUtils.isManageEndPoint();
if (!manageEndPoint) {
pageReqVO.setOrganId(SecurityFrameworkUtils.getUserOrganId());
}
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<BalanceDetailsRespVO> list = incomeExpenseService.getBalanceDetailsPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "余额明细表.xls", "数据", BalanceDetailsRespVO.class,
BeanUtils.toBean(list, BalanceDetailsRespVO.class));
}
}
@@ -1,77 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.balancedetails.vo;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.module.system.validation.pay.IncomeExpenseTypeEnumValid;
import com.cf.imes.module.system.validation.pay.TradeTypeEnumValid;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
@Schema(description = "管理后台 - 组织账户明细分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BalanceDetailsPageReqVO extends PageParam {
@Schema(description = "流水号")
@Size(max = 64, message = "流水号长度不能超过64个字符")
private String businessNo;
@Schema(description = "订单号")
@Size(max = 64, message = "订单号长度不能超过64个字符")
private String orderNo;
@Schema(description = "交易类型")
@TradeTypeEnumValid
private Integer tradeType;
@Schema(description = "收支类型,0收入 1支出")
@IncomeExpenseTypeEnumValid
private Integer incomeExpenseType;
@Schema(description = "创建时间", example = "[2022-07-01 ,2022-07-01]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate[] createTime;
@Schema(hidden = true)
private LocalDateTime[] operateTime;
@Schema(description = "充值金额")
@DecimalMin(value = "0.01", message = "充值金额必须大于零")
@DecimalMax(value = "100000", message = "充值金额不能超过十万")
@Digits(integer = 6, fraction = 2, message = "支付金额格式不正确")
private BigDecimal rechargeAmount;
@Schema(description = "赠送金额")
@DecimalMin(value = "0", message = "赠送金额不能小于零")
@DecimalMax(value = "100000", message = "赠送金额不能超过十万")
@Digits(integer = 6, fraction = 2, message = "赠送金额格式不正确")
private BigDecimal giftAmount;
@Schema(description = "产品金额")
@DecimalMin(value = "0.01", message = "产品购买金额必须大于零")
@DecimalMax(value = "100000", message = "产品购买金额不能超过十万")
@Digits(integer = 6, fraction = 2, message = "产品购买金额格式不正确")
private BigDecimal productPrice;
@Schema(description = "组织ID")
private Long organId;
@Schema(description = "操作人")
@Size(max = 64, message = "操作人长度不能超过64个字符")
private String operator;
}
@@ -1,74 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.balancedetails.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.cf.imes.framework.excel.core.annotations.EnumFormat;
import com.cf.imes.framework.excel.core.convert.EnumConvert;
import com.cf.imes.module.system.enums.pay.IncomeExpenseTypeEnum;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@Schema(description = "管理后台 - 组织账户明细 Response VO")
public class BalanceDetailsRespVO {
@Schema(description = "组织名称")
@ExcelProperty("组织名称")
private String organName;
@Schema(description = "流水号")
@ExcelProperty("流水号")
private String businessNo;
@Schema(description = "交易类型,0充值 1软件购买")
@ExcelProperty(value = "交易类型",converter = EnumConvert.class)
@EnumFormat(value = TradeTypeEnum.class)
private Integer tradeType;
@Schema(description = "订单号")
@ExcelProperty("订单号")
private String orderNo;
@Schema(description = "收支类型,0收入 1支出")
@ExcelProperty(value = "收支类型",converter = EnumConvert.class)
@EnumFormat(value = IncomeExpenseTypeEnum.class)
private Integer incomeExpenseType;
@Schema(description = "充值金额")
@ExcelProperty("充值金额")
private BigDecimal rechargeAmount;
@Schema(description = "赠送金金额")
@ExcelProperty("赠送金金额")
private BigDecimal rechargeGiftAmount;
@Schema(description = "产品金额")
@ExcelProperty("产品金额")
private BigDecimal productPrice;
@Schema(description = "账户余额支付")
@ExcelProperty("账户余额支付")
private BigDecimal balancePayAmount;
@Schema(description = "扫码支付")
@ExcelProperty("扫码支付")
private BigDecimal rechargePayAmount;
@Schema(description = "账户赠送金支付")
@ExcelProperty("账户赠送金支付")
private BigDecimal giftPayAmount;
@Schema(description = "交易时间")
@ExcelProperty("交易时间")
private LocalDateTime createTime;
@Schema(description = "操作人")
@ExcelProperty("操作人")
private String creator;
@Schema(description = "支付方式")
private String paymentMethod;
}
@@ -1,45 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.manualadjust;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceRespVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceSaveReqVO;
import com.cf.imes.module.system.service.funds.manualadjust.ManualAdjustAccountBalanceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
/**
* @author Gqr
* @since 2025/9/16 10:28
*/
@Tag(name = "管理后台 - 手工调账管理")
@RestController
@RequestMapping("/system/balance/manualadjust")
@Validated
public class ManualAdjustAccountBalanceController {
@Resource
private ManualAdjustAccountBalanceService manualAdjustAccountBalanceService;
@PutMapping()
@Operation(summary = "手工调账")
public CommonResult<Long> createAjustment(@RequestBody @Valid ManualAdjustAccountBalanceSaveReqVO saveReqVO) {
return success(manualAdjustAccountBalanceService.createAjustment(saveReqVO));
}
@GetMapping("/page")
@Operation(summary = "获取手工调账分页")
public CommonResult<PageResult<ManualAdjustAccountBalanceRespVO>> getAdjustPage(@Valid ManualAdjustAccountBalancePageReqVO pageReqVO) {
return success(manualAdjustAccountBalanceService.getPage(pageReqVO));
}
}
@@ -1,40 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.manualadjust.vo;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.module.system.validation.manualadjust.AdjustTypeValid;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* @author Gqr
* @since 2025/9/16 14:40
*/
@Schema(description = "管理后台 - 手工调账分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ManualAdjustAccountBalancePageReqVO extends PageParam {
@Schema(description = "组织id", example = "1")
private Long organId;
@Schema(description = "调账类型", example = "0")
@AdjustTypeValid
private Integer adjustType;
@Schema(description = "备注")
@Size(max = 255, message = "备注长度不能超过255个字符")
private String remark;
@Schema(description = "交易时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}
@@ -1,40 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.manualadjust.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* @author Gqr
* @since 2025/9/16 14:35
*/
@Schema(description = "管理后台 - 手工调账 Response VO")
@Data
public class ManualAdjustAccountBalanceRespVO {
@Schema(description = "流水号")
private String businessNo;
@Schema(description = "组织名称")
private String organName;
@Schema(description = "调账类型,0:调增、1:调减")
private Integer adjustType;
@Schema(description = "充值金额")
private BigDecimal cashAmountChange;
@Schema(description = "赠送金额")
private BigDecimal giftAmountChange;
@Schema(description = "备注")
private String remark;
@Schema(description = "交易时间")
private LocalDateTime createTime;
@Schema(description = "操作人")
private String creator;
}
@@ -1,45 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.manualadjust.vo;
import com.cf.imes.module.system.validation.manualadjust.AdjustTypeValid;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author Gqr
* @since 2025/9/16 10:29
*/
@Schema(description = "管理后台 - 新增手工调账 Request VO")
@Data
public class ManualAdjustAccountBalanceSaveReqVO {
@Schema(description = "组织编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "组织编号不能为空")
private Long organId;
@Schema(description = "手工调账类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "手工调账类型不能为空")
@AdjustTypeValid
private Integer adjustType;
@Schema(description = "充值金额")
@DecimalMin(value = "0.01", message = "充值金额必须大于零")
@DecimalMax(value = "100000", message = "充值金额不能超过十万")
@Digits(integer = 6, fraction = 2, message = "支付金额格式不正确")
private BigDecimal rechargeAmount;
@Schema(description = "赠送金额")
@DecimalMin(value = "0", message = "赠送金额不能小于零")
@DecimalMax(value = "100000", message = "赠送金额不能超过十万")
@Digits(integer = 6, fraction = 2, message = "赠送金额格式不正确")
private BigDecimal giftAmount;
@Schema(description = "备注")
@Size(max = 255, message = "备注长度不能超过255个字符")
private String remark;
}
@@ -1,21 +1,14 @@
package com.cf.imes.module.system.controller.admin.funds.organamount;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.ManageAmountOverviewRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAvailableAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganFundsStatisticsReqVO;
import com.cf.imes.module.system.service.funds.organamount.OrganAmountService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.security.PermitAll;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
@@ -38,26 +31,6 @@ public class OrganAmountController {
@Resource
private OrganAmountService organAmountService;
@GetMapping("")
@Operation(summary = "获取组织余额数据")
public CommonResult<OrganAmountRespVO> getOrganAmount() {
return success(organAmountService.getOrganAmount());
}
@GetMapping("/available")
@Operation(summary = "获取组织可用金")
public CommonResult<OrganAvailableAmountRespVO> getOrganAvailableAmount() {
return success(organAmountService.getOrganAvailableAmount());
}
@GetMapping("/manage/available")
@Operation(summary = "获取管理端组织可用金")
@Parameter(name = "organId", description = "组织id", example = "10")
public CommonResult<OrganAvailableAmountRespVO> getManageAvailableAmount(@RequestParam(value = "organId", required = false) Long organId) {
return success(organAmountService.getManageAvailableAmount(organId));
}
@GetMapping("/manage/total")
@Operation(summary = "获取管理端资金总览")
public CommonResult<ManageAmountOverviewRespVO> getManageTotalAmount() {
@@ -75,13 +48,4 @@ public class OrganAmountController {
public CommonResult<Map<String, Object>> getManageConsumptionTrend(@Valid OrganFundsStatisticsReqVO reqVO) {
return success(organAmountService.getConsumptionTrend(reqVO, false));
}
@PostMapping("/fix")
@Operation(summary = "修正组织余额")
@PermitAll
@OperateLog(enable = false)
public CommonResult<Boolean> fixOrganAmount() {
organAmountService.fixOrganAmount();
return success(true);
}
}
@@ -9,16 +9,9 @@ import java.math.BigDecimal;
@Schema(description = "管理后台 - 管理端资金总览 Response VO")
@Data
public class ManageAmountOverviewRespVO {
@Schema(description = "销售总额现充支付")
@Schema(description = "销售总额")
private BigDecimal totalSalesAmount;
@Schema(description = "销售总额赠送金支付")
private BigDecimal totalSalesGiftAmount;
@Schema(description = "充值余额")
private BigDecimal rechargeBalance;
@Schema(description = "待审核的发票金额")
private BigDecimal toExamineAmount;
}
@@ -6,7 +6,7 @@ import lombok.Data;
import java.math.BigDecimal;
/**
* 销售总额明细:充值、赠送
* 销售总额明细
*
* @author Gqr
* @since 2025/8/14 15:20
@@ -15,12 +15,7 @@ import java.math.BigDecimal;
@AllArgsConstructor
public class TotalSalesAmountRespVO {
/**
* 现充支付总额
* 销售总额
*/
private BigDecimal amount;
/**
* 赠送金支付总额
*/
private BigDecimal giftAmount;
}
@@ -0,0 +1,66 @@
package com.cf.imes.module.system.controller.admin.funds.productpromotion;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionRespVO;
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.productpromotion.ProductPromotionDO;
import com.cf.imes.module.system.service.funds.productpromotion.ProductPromotionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 优惠活动管理")
@RestController
@RequestMapping("/system/product/promotion")
@Validated
public class ProductPromotionController {
@Resource
private ProductPromotionService productPromotionService;
@PutMapping("")
@Operation(summary = "新建优惠活动")
public CommonResult<Long> createProductPromotion(@Valid @RequestBody ProductPromotionSaveReqVO createReqVO) {
return success(productPromotionService.create(createReqVO));
}
@PostMapping("")
@Operation(summary = "更新优惠活动")
public CommonResult<Boolean> updateProductPromotion(@Valid @RequestBody ProductPromotionSaveReqVO updateReqVO) {
productPromotionService.update(updateReqVO);
return success(true);
}
@DeleteMapping("/{id}")
@Operation(summary = "删除优惠活动")
@Parameter(name = "id", description = "编号", required = true)
public CommonResult<Boolean> deleteProductPromotion(@PathVariable("id") Long id) {
productPromotionService.delete(id);
return success(true);
}
@GetMapping("/{id}")
@Operation(summary = "获取优惠活动")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<ProductPromotionRespVO> getProductPromotion(@PathVariable("id") Long id) {
ProductPromotionDO giftMoneyDetailsDO = productPromotionService.get(id);
return success(BeanUtils.toBean(giftMoneyDetailsDO, ProductPromotionRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获取优惠活动分页")
public CommonResult<PageResult<ProductPromotionRespVO>> getProductPromotionPage(@Valid ProductPromotionPageReqVO pageReqVO) {
PageResult<ProductPromotionDO> pageResult = productPromotionService.getPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, ProductPromotionRespVO.class));
}
}
@@ -1,24 +1,21 @@
package com.cf.imes.module.system.controller.admin.funds.recharge.vo;
package com.cf.imes.module.system.controller.admin.funds.productpromotion.vo;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.module.system.validation.recharge.RechargeGiftTypeValid;
import com.cf.imes.module.system.validation.recharge.RechargeType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 赠送金活动表 gift_money Request VO")
@Schema(description = "管理后台 - 优惠活动表 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RechargePageReqVO extends PageParam {
public class ProductPromotionPageReqVO extends PageParam {
@Schema(description = "活动id", example = "1")
private Long id;
@@ -26,19 +23,11 @@ public class RechargePageReqVO extends PageParam {
@Schema(description = "活动名称", example = "赵六")
private String activityName;
@Schema(description = "赠送类型,0:满X送X、1:每满X送X", example = "0")
@RechargeGiftTypeValid
private Integer rechargeGiftType;
@Schema(description = "购买时长",example = "1")
private Integer purchaseDuration;
@Schema(description = "充值类型,0:微信&支付宝、1:微信、2:支付宝", example = "0")
@RechargeType
private Integer rechargeType;
@Schema(description = "充值金额")
private BigDecimal rechargeAmount;
@Schema(description = "赠送金额")
private BigDecimal giftAmount;
@Schema(description = "赠送时长",example = "1")
private Integer giftDuration;
@Schema(description = "投放时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@@ -51,9 +40,6 @@ public class RechargePageReqVO extends PageParam {
@Schema(description = "备注")
private String remark;
@Schema(description = "是否删除")
private Boolean deleted;
@Schema(description = "排序", example = "ascend")
private String order;
@@ -1,19 +1,18 @@
package com.cf.imes.module.system.controller.admin.funds.recharge.vo;
package com.cf.imes.module.system.controller.admin.funds.productpromotion.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 赠送金活动表 gift_money Request VO")
@Schema(description = "管理后台 - 优惠活动表 Request VO")
@Data
@ExcelIgnoreUnannotated
public class RechargeRespVO {
public class ProductPromotionRespVO {
@Schema(description = "活动id", example = "1")
private Long id;
@@ -21,23 +20,20 @@ public class RechargeRespVO {
@Schema(description = "活动名称", example = "赵六")
private String activityName;
@Schema(description = "赠送类型", example = "0满X送X 1每满X送X")
private Integer rechargeGiftType;
@Schema(description = "购买时长",example = "1")
private Integer purchaseDuration;
@Schema(description = "充值类型", example = "0微信、支付宝 1微信 2支付宝")
private Integer rechargeType;
@Schema(description = "购买时长单位,0:年、1:月、2:日",example = "1")
private Integer purchaseDurationUnit;
@Schema(description = "充值金额")
private BigDecimal rechargeAmount;
@Schema(description = "赠送时长",example = "1")
private Integer giftDuration;
@Schema(description = "赠送金额")
private BigDecimal giftAmount;
@Schema(description = "投放开始时间")
@Schema(description = "开始时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime startTime;
@Schema(description = "投放结束时间")
@Schema(description = "结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime endTime;
@@ -0,0 +1,54 @@
package com.cf.imes.module.system.controller.admin.funds.productpromotion.vo;
import com.cf.imes.module.system.validation.products.DurationUnitValid;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 优惠活动表 新增/修改 Request VO")
@Data
public class ProductPromotionSaveReqVO {
@Schema(description = "活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@NotNull(message = "活动名称不能为空")
private String activityName;
@Schema(description = "购买时长",example = "1")
@NotNull(message = "购买时长不能为空")
private Integer purchaseDuration;
@Schema(description = "产品ID", example = "1")
@NotNull(message = "关联产品不能为空")
private Long productId;
@Schema(description = "购买时长单位,0:年、1:月、2:日",example = "1")
@DurationUnitValid
@NotNull(message = "购买时长单位不能为空")
private Integer purchaseDurationUnit;
@Schema(description = "赠送时长",example = "1")
@NotNull(message = "赠送时长不能为空")
private Integer giftDuration;
@Schema(description = "赠送时长单位",example = "1")
@DurationUnitValid
@NotNull(message = "赠送时长单位不能为空")
private Integer giftDurationUnit;
@Schema(description = "开始时间")
@NotNull(message = "开始时间不能为空")
private LocalDateTime startTime;
@Schema(description = "结束时间")
@NotNull(message = "结束时间不能为空")
private LocalDateTime endTime;
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
private String remark;
}
@@ -1,9 +1,7 @@
package com.cf.imes.module.system.controller.admin.funds.products.vo.product;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.organamount.OrganAmountDO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderDO;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -22,21 +20,11 @@ public class ProductProcessorRespVO {
*/
private PurchaseRecordDO purchaseRecordDO;
/**
* 收支明细
*/
private IncomeExpenseDetailsDO incomeExpenseDetailsDO;
/**
* 外部支付信息
*/
private PayOrderDO payOrderDO;
/**
* 组织资金
*/
private OrganAmountDO organAmountDO;
/**
* 延期记录列表
*/
@@ -1,20 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.purchase.vo;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 查询组织下最早购买产品记录和关联定价规则 response vo
*
* @author Gqr
* @since 2025/8/19 17:10
*/
@Data
@AllArgsConstructor
public class OrgEarliestPurchaseProductRespVO {
/**
* 购买记录
*/
private PurchaseRecordDO purchaseRecordDO;
}
@@ -35,14 +35,6 @@ public class SalesDetailRespVO {
@ExcelProperty("扫码支付")
private BigDecimal rechargeSpent;
@Schema(description = "现金支付")
@ExcelProperty("现金支付")
private BigDecimal accountBalanceSpent;
@Schema(description = "账户赠送金支付")
@ExcelProperty("账户赠送金支付")
private BigDecimal giftMoneySpent;
@Schema(description = "操作人")
@ExcelProperty("操作人")
private String creator;
@@ -1,75 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.recharge;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeRespVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.recharge.GiftMoneyDetailsDO;
import com.cf.imes.module.system.service.funds.recharge.RechargeActiveService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 充值活动管理")
@RestController
@RequestMapping("/system/recharge-active")
@Validated
public class RechargeActiveController {
@Resource
private RechargeActiveService productsService;
@PutMapping("")
@Operation(summary = "新建充值活动")
public CommonResult<Long> createRechargeActive(@Valid @RequestBody RechargeSaveReqVO createReqVO) {
return success(productsService.create(createReqVO));
}
@PostMapping("")
@Operation(summary = "更新充值活动")
public CommonResult<Boolean> updateRechargeActive(@Valid @RequestBody RechargeSaveReqVO updateReqVO) {
productsService.update(updateReqVO);
return success(true);
}
@DeleteMapping("/{id}")
@Operation(summary = "删除充值活动")
@Parameter(name = "id", description = "编号", required = true)
public CommonResult<Boolean> deleteRechargeActive(@PathVariable("id") Long id) {
productsService.delete(id);
return success(true);
}
@GetMapping("/{id}")
@Operation(summary = "获取充值活动")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<RechargeRespVO> getRechargeActive(@PathVariable("id") Long id) {
GiftMoneyDetailsDO giftMoneyDetailsDO = productsService.get(id);
return success(BeanUtils.toBean(giftMoneyDetailsDO, RechargeRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获取充值活动分页")
public CommonResult<PageResult<RechargeRespVO>> getRechargeActivePage(@Valid RechargePageReqVO pageReqVO) {
PageResult<GiftMoneyDetailsDO> pageResult = productsService.getPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, RechargeRespVO.class));
}
@GetMapping("/available")
@Operation(summary = "获取可用充值活动")
public CommonResult<List<RechargeRespVO>> getAvailableRechargeActivePage() {
List<GiftMoneyDetailsDO> pageResult = productsService.getAvailableRechargeActiveList();
return success(BeanUtils.toBean(pageResult, RechargeRespVO.class));
}
}
@@ -1,34 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.recharge;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsBalanceInfoRespVO;
import com.cf.imes.module.system.service.funds.recharge.RechargeDetailsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
/**
* @author Gqr
* @since 2025/9/11 16:18
*/
@Tag(name = "管理后台 - 充值明细管理")
@RestController
@RequestMapping("/system/rechargeDetails")
@Validated
public class RechargeDetailsController {
@Resource
private RechargeDetailsService rechargeDetailsService;
@GetMapping("/balance")
@Operation(summary = "获取管理端充值明细余额信息")
public CommonResult<RechargeDetailsBalanceInfoRespVO> getManageRechargeDetailsBalanceInfo() {
return success(rechargeDetailsService.getManageRechargeDetailsBalanceInfo());
}
}
@@ -1,72 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.recharge.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.cf.imes.framework.excel.core.annotations.EnumFormat;
import com.cf.imes.framework.excel.core.convert.EnumConvert;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* @author Gqr
* @since 2025/9/11 18:26
*/
@Schema(description = "管理后台 - 充值明细 Resp VO")
@Data
public class RechargeDetailRespVO {
@Schema(description = "流水号")
@ExcelProperty("流水号")
private Long id;
@Schema(description = "交易类型,0充值 1软件购买")
@ExcelProperty(value = "交易类型", converter = EnumConvert.class)
@EnumFormat(value = TradeTypeEnum.class)
private Integer tradeType;
@Schema(description = "充值金额")
@ExcelProperty("充值金额")
private BigDecimal rechargeAmount;
@Schema(description = "赠送金金额")
@ExcelProperty("赠送金金额")
private BigDecimal rechargeGiftAmount;
@ExcelIgnore
private Long purchaseId;
@Schema(description = "产品金额")
@ExcelProperty("产品金额")
private BigDecimal totalAmount;
@Schema(description = "扫码支付")
@ExcelProperty("扫码支付")
private BigDecimal rechargeSpent;
@Schema(description = "现金支付")
@ExcelProperty("现金支付")
private BigDecimal accountBalanceSpent;
@Schema(description = "账户赠送金支付")
@ExcelProperty("账户赠送金支付")
private BigDecimal giftMoneySpent;
@Schema(description = "操作人")
@ExcelProperty("操作人")
private String creator;
@Schema(description = "组织名称")
@ExcelProperty("组织名称")
private String organName;
@Schema(description = "交易时间")
@ExcelProperty("交易时间")
private LocalDateTime createTime;
@Schema(description = "支付方式")
private String paymentMethod;
}
@@ -1,21 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.recharge.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author Gqr
* @since 2025/9/12 14:33
*/
@Schema(description = "管理后台 - 充值明细充值余额信息 Resp VO")
@Data
public class RechargeDetailsBalanceInfoRespVO {
@Schema(description = "充值总额", example = "100")
private BigDecimal rechargeAmount;
@Schema(description = "充值使用金额", example = "100")
private BigDecimal rechargeUsageAmount;
}
@@ -1,44 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.recharge.vo;
import com.cf.imes.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* @author Gqr
* @since 2025/9/11 17:45
*/
@Schema(description = "管理后台 - 充值明细分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RechargeDetailsPageReqVO extends PageParam {
@Schema(description = "组织ID")
private Long organId;
@Schema(description = "产品金额")
@DecimalMin(value = "0.01", message = "产品购买金额必须大于零")
@DecimalMax(value = "100000", message = "产品购买金额不能超过十万")
@Digits(integer = 6, fraction = 2, message = "产品购买金额格式不正确")
private BigDecimal productPrice;
@Schema(description = "操作人")
@Size(max = 64, message = "操作人长度不能超过64个字符")
private String operator;
@Schema(description = "交易时间", example = "[2022-07-01 01:01:01 ,2022-07-01 01:01:01]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}
@@ -1,55 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.recharge.vo;
import com.cf.imes.module.system.validation.recharge.MoneyValid;
import com.cf.imes.module.system.validation.recharge.RechargeGiftTypeValid;
import com.cf.imes.module.system.validation.recharge.RechargeType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 赠送金活动表 gift_money 新增/修改 Request VO")
@Data
public class RechargeSaveReqVO {
@Schema(description = "活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@NotNull(message = "活动名称不能为空")
private String activityName;
@Schema(description = "赠送类型,0:满X送X、1:每满X送X", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "赠送类型不能为空")
@RechargeGiftTypeValid
private Integer rechargeGiftType;
@Schema(description = "充值类型,0:微信&支付宝、1:微信、2:支付宝", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "充值类型不能为空")
@RechargeType
private Integer rechargeType;
@Schema(description = "充值金额",requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "充值金额不能为空")
@MoneyValid(name = "充值金额")
private BigDecimal rechargeAmount;
@Schema(description = "赠送金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "赠送金额不能为空")
@MoneyValid(name = "赠送金额")
private BigDecimal giftAmount;
@Schema(description = "开始时间")
@NotNull(message = "开始时间不能为空")
private LocalDateTime startTime;
@Schema(description = "结束时间")
@NotNull(message = "结束时间不能为空")
private LocalDateTime endTime;
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
private String remark;
}
@@ -4,7 +4,6 @@ import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayProductOrderUnifiedReqVO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayRechargeOrderReqVO;
import com.cf.imes.module.system.service.pay.PayOrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -41,13 +40,6 @@ public class PayController {
@Resource
private PayOrderService payOrderService;
@PostMapping("/recharge")
@Operation(summary = "创建充值支付订单")
public CommonResult<PayOrderRespDTO> recharge(@RequestBody PayRechargeOrderReqVO payRechargeOrderReqVO) {
PayOrderRespDTO payOrderRespDTO = payOrderService.rechargePay(payRechargeOrderReqVO);
return success(payOrderRespDTO);
}
@PostMapping("/product")
@Operation(summary = "创建产品支付订单")
public CommonResult<PayOrderRespDTO> productPay(@RequestBody PayProductOrderUnifiedReqVO payProductOrderUnifiedReqVO) {
@@ -1,5 +1,6 @@
package com.cf.imes.module.system.controller.admin.pay.vo;
import com.cf.imes.module.system.validation.pay.PayChannelCodeValid;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
@@ -27,6 +28,7 @@ public class PayProductOrderUnifiedReqVO {
@Schema(description = "产品支付渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "产品支付渠道编码不能为空", groups = PayProductGroup.class)
@PayChannelCodeValid
private Integer productChannelCode;
@Schema(description = "机构编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@@ -1,42 +0,0 @@
package com.cf.imes.module.system.controller.admin.pay.vo;
import com.cf.imes.module.system.validation.pay.PayChannelCodeValid;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
/**
* 充值支付vo
*
* @author Gqr
* @since 2025/4/15 14:30
*/
@Data
@Valid
public class PayRechargeOrderReqVO {
@Schema(description = "组织编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "组织编号不能为空")
private Long organId;
@Schema(description = "支付金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "支付金额不能为空")
@DecimalMin(value = "0.01", message = "支付金额必须大于零")
@DecimalMax(value = "100000", message = "支付金额不能超过十万")
@Digits(integer = 6, fraction = 2, message = "支付金额格式不正确")
private BigDecimal price;
@Schema(description = "支付渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@PayChannelCodeValid
@NotNull(message = "支付渠道编码不能为空")
private Integer channelCode;
@Schema(description = "充值活动规格编号", example = "0")
private Long rechargeActivityId;
}
@@ -1,4 +1,4 @@
package com.cf.imes.module.system.dal.dataobject.funds.recharge;
package com.cf.imes.module.system.dal.dataobject.funds.productpromotion;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -6,23 +6,22 @@ import com.baomidou.mybatisplus.annotation.TableName;
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 赠送金规则表 gift_money_details DO
* 产品优惠活动 product_promotion DO
*
* @author 晨丰科技
*/
@TableName("gift_money_details")
@KeySequence("gift_money_details_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@TableName("product_promotion")
@KeySequence("product_promotion_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GiftMoneyDetailsDO extends BaseDO {
public class ProductPromotionDO extends BaseDO {
/**
* 产品 ID
@@ -33,22 +32,37 @@ public class GiftMoneyDetailsDO extends BaseDO {
* 活动名称
*/
private String activityName;
/**
* 赠送类型 0满X送X 1每满X送X
* 产品ID
*/
private Integer rechargeGiftType;
private Long productId;
/**
* 充值类型 0微信支付宝 1微信 2支付宝
* 产品名称
*/
private Integer rechargeType;
private String productName;
/**
* 充值金额
* 购买时长
*/
private BigDecimal rechargeAmount;
private Integer purchaseDuration;
/**
* 赠送金额
* 购买时长单位012
*/
private BigDecimal giftAmount;
private Integer purchaseDurationUnit;
/**
* 赠送时长
*/
private Integer giftDuration;
/**
* 赠送时长单位
*/
private Integer giftDurationUnit;
/**
* 活动开始时间
*/
@@ -59,6 +59,10 @@ public class PurchaseRecordDO extends BaseDO {
*/
private Long productDetailsId;
/**
* 优惠活动ID
*/
private Long productPromotionId;
/**
* 产品名称
@@ -109,22 +113,11 @@ public class PurchaseRecordDO extends BaseDO {
*/
private BigDecimal monthAverageAmount;
/**
* 现金余额支出
*/
private BigDecimal accountBalanceSpent;
/**
* 第三方支付金额
*/
private BigDecimal externalSpent;
/**
* 赠送金
*/
private BigDecimal giftMoneySpent;
/**
* 货币类型
@@ -49,12 +49,6 @@ public class IncomeExpenseDetailsDO extends BaseDO {
private Long organId;
/**
* 充值-赠送金规则表
*/
private Long giftMoneyId;
/**
* 购买-购买记录id
*/
@@ -72,38 +66,11 @@ public class IncomeExpenseDetailsDO extends BaseDO {
*/
private Integer incomeExpenseType;
/**
* 支出/入账现金金额
*/
private BigDecimal cashAmountChange;
/**
* 支出/入账赠送金金额
*/
private BigDecimal giftAmountChange;
/**
* 可用余额
*/
private BigDecimal availableAmount;
/**
* 现金金额
* 支金额
*/
private BigDecimal amount;
/**
* 赠送金额
*/
private BigDecimal giftAmount;
/**
* 货币类型
*/
@@ -2,13 +2,11 @@ package com.cf.imes.module.system.dal.mysql.funds.organamount;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAmountGroupByCreateTimeRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAvailableAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganFundsStatisticsReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.organamount.OrganAmountDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
@Mapper
@@ -21,19 +19,4 @@ public interface OrganAmountMapper extends BaseMapperX<OrganAmountDO> {
* @return
*/
List<OrganAmountGroupByCreateTimeRespVO> selectOrganIncomeExpenseTrendGroupByCreateTime(@Param("req") OrganFundsStatisticsReqVO reqVO, @Param("organId") Long organId);
/**
* 查询充值余额总额
*
* @return
*/
BigDecimal getTotalRechargeAmount();
/**
* 查询所有组织的可用金
*
* @return
*/
OrganAvailableAmountRespVO getTotalAvailableAmount();
}
@@ -0,0 +1,58 @@
package com.cf.imes.module.system.dal.mysql.funds.productpromotion;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionPageReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.productpromotion.ProductPromotionDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 产品优惠活动 product_promotion Mapper
*
* @author 晨丰科技
*/
@Mapper
public interface ProductPromotionMapper extends BaseMapperX<ProductPromotionDO> {
default PageResult<ProductPromotionDO> selectPage(ProductPromotionPageReqVO reqVO) {
LambdaQueryWrapperX<ProductPromotionDO> queryWrapper = new LambdaQueryWrapperX<ProductPromotionDO>()
.likeIfPresent(ProductPromotionDO::getActivityName, reqVO.getActivityName())
.eqIfPresent(ProductPromotionDO::getPurchaseDuration, reqVO.getPurchaseDuration())
.eqIfPresent(ProductPromotionDO::getGiftDuration, reqVO.getGiftDuration())
.betweenIfPresent(ProductPromotionDO::getStartTime, reqVO.getStartTime())
.betweenIfPresent(ProductPromotionDO::getEndTime, reqVO.getEndTime())
.likeIfPresent(ProductPromotionDO::getRemark, reqVO.getRemark());
if (reqVO.getOrder() == null) {
queryWrapper.orderByDesc(ProductPromotionDO::getId);
}else {
if (reqVO.getOrder().equals("ascend")) {
switch (reqVO.getField()) {
case "id" -> queryWrapper.orderByAsc(ProductPromotionDO::getId);
case "purchaseDuration" -> queryWrapper.orderByAsc(ProductPromotionDO::getPurchaseDuration);
case "giftDuration" -> queryWrapper.orderByAsc(ProductPromotionDO::getGiftDuration);
case "startTime" -> queryWrapper.orderByAsc(ProductPromotionDO::getStartTime);
case "endTime" -> queryWrapper.orderByAsc(ProductPromotionDO::getEndTime);
case "updateTime" -> queryWrapper.orderByAsc(ProductPromotionDO::getUpdateTime);
default -> {
// default不排序
}
}
}else if (reqVO.getOrder().equals("descend")) {
switch (reqVO.getField()) {
case "id" -> queryWrapper.orderByDesc(ProductPromotionDO::getId);
case "purchaseDuration" -> queryWrapper.orderByDesc(ProductPromotionDO::getPurchaseDuration);
case "giftDuration" -> queryWrapper.orderByDesc(ProductPromotionDO::getGiftDuration);
case "startTime" -> queryWrapper.orderByDesc(ProductPromotionDO::getStartTime);
case "endTime" -> queryWrapper.orderByDesc(ProductPromotionDO::getEndTime);
case "updateTime" -> queryWrapper.orderByDesc(ProductPromotionDO::getUpdateTime);
default -> {
// default不排序
}
}
}
}
return selectPage(reqVO, queryWrapper);
}
}
@@ -1,6 +1,5 @@
package com.cf.imes.module.system.dal.mysql.funds.purchase;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cf.imes.framework.common.pojo.PageResult;
@@ -28,14 +27,6 @@ import java.util.List;
*/
@Mapper
public interface PurchaseRecordMapper extends BaseMapperX<PurchaseRecordDO> {
/**
* 查询机构下可开票的金额
*
* @param organId
* @return
*/
BigDecimal getInvoicingAmount(Long organId);
/**
* 分页查询
*
@@ -115,13 +106,6 @@ public interface PurchaseRecordMapper extends BaseMapperX<PurchaseRecordDO> {
*/
BigDecimal getTodaySales();
/**
* 查询购买记录中的现金使用金额总数
*
* @return
*/
BigDecimal getTotalRechargeUsageAmount();
/**
* 分页查询销售记录
*
@@ -137,8 +121,8 @@ public interface PurchaseRecordMapper extends BaseMapperX<PurchaseRecordDO> {
.eq(PurchaseRecordDO::getDeleted, false)
.ne(PurchaseRecordDO::getInitial, true)
.orderByDesc(PurchaseRecordDO::getCreateTime)
.select(PurchaseRecordDO::getId, PurchaseRecordDO::getOrganId, PurchaseRecordDO::getTotalAmount, PurchaseRecordDO::getAccountBalanceSpent, PurchaseRecordDO::getExternalSpent,
PurchaseRecordDO::getGiftMoneySpent, PurchaseRecordDO::getCreator, PurchaseRecordDO::getCreateTime, PurchaseRecordDO::getPaymentMethod)
.select(PurchaseRecordDO::getId, PurchaseRecordDO::getOrganId, PurchaseRecordDO::getTotalAmount, PurchaseRecordDO::getExternalSpent,
PurchaseRecordDO::getCreator, PurchaseRecordDO::getCreateTime, PurchaseRecordDO::getPaymentMethod)
);
}
@@ -1,69 +0,0 @@
package com.cf.imes.module.system.dal.mysql.funds.recharge;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargePageReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.recharge.GiftMoneyDetailsDO;
import com.cf.imes.module.system.enums.recharge.RechargeTypeEnum;
import org.apache.ibatis.annotations.Mapper;
import java.util.Arrays;
/**
* 赠送金活动详情表 gift_money_details Mapper
*
* @author 晨丰科技
*/
@Mapper
public interface GiftMoneyDetailsMapper extends BaseMapperX<GiftMoneyDetailsDO> {
default PageResult<GiftMoneyDetailsDO> selectPage(RechargePageReqVO reqVO) {
LambdaQueryWrapperX<GiftMoneyDetailsDO> queryWrapper = new LambdaQueryWrapperX<GiftMoneyDetailsDO>()
.likeIfPresent(GiftMoneyDetailsDO::getActivityName, reqVO.getActivityName())
.eqIfPresent(GiftMoneyDetailsDO::getRechargeGiftType, reqVO.getRechargeGiftType())
.eqIfPresent(GiftMoneyDetailsDO::getGiftAmount, reqVO.getGiftAmount())
.eqIfPresent(GiftMoneyDetailsDO::getRechargeAmount, reqVO.getRechargeAmount())
.betweenIfPresent(GiftMoneyDetailsDO::getStartTime, reqVO.getStartTime())
.betweenIfPresent(GiftMoneyDetailsDO::getEndTime, reqVO.getEndTime())
.eqIfPresent(GiftMoneyDetailsDO::getDeleted, reqVO.getDeleted());
Integer rechargeType = reqVO.getRechargeType();
// WECHAT_AND_ALIPAY查全部、否则查WECHAT_AND_ALIPAY+查询类型
if (ObjectUtil.isNotNull(rechargeType) && !RechargeTypeEnum.isWechatAndAlipay(rechargeType)) {
queryWrapper.in(GiftMoneyDetailsDO::getRechargeType, Arrays.asList(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus(), rechargeType));
}
if (reqVO.getOrder() == null) {
queryWrapper.orderByDesc(GiftMoneyDetailsDO::getId);
}else {
if (reqVO.getOrder().equals("ascend")) {
switch (reqVO.getField()) {
case "id" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getId);
case "rechargeAmount" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getRechargeAmount);
case "giftAmount" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getGiftAmount);
case "startTime" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getStartTime);
case "endTime" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getEndTime);
case "updateTime" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getUpdateTime);
default -> {
// default不排序
}
}
}else if (reqVO.getOrder().equals("descend")) {
switch (reqVO.getField()) {
case "id" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getId);
case "rechargeAmount" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getRechargeAmount);
case "giftAmount" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getGiftAmount);
case "startTime" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getStartTime);
case "endTime" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getEndTime);
case "updateTime" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getUpdateTime);
default -> {
// default不排序
}
}
}
}
return selectPage(reqVO, queryWrapper);
}
}
@@ -1,19 +1,8 @@
package com.cf.imes.module.system.dal.mysql.incomeandexpense;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.funds.balancedetails.vo.BalanceDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.AccountDetailsDO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
import com.cf.imes.module.system.enums.pay.AdjustTypeEnum;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 收支明细 Mapper
*
@@ -22,59 +11,4 @@ import org.apache.ibatis.annotations.Param;
*/
@Mapper
public interface IncomeExpenseDetailsMapper extends BaseMapperX<IncomeExpenseDetailsDO> {
/**
* 获取余额明细
*
* @param pageReqVO
* @return
*/
default PageResult<IncomeExpenseDetailsDO> selectDetailsPage(BalanceDetailsPageReqVO pageReqVO) {
LambdaQueryWrapperX<IncomeExpenseDetailsDO> queryWrapperX = new LambdaQueryWrapperX<IncomeExpenseDetailsDO>()
.eqIfPresent(IncomeExpenseDetailsDO::getOrganId, pageReqVO.getOrganId())
.eq(IncomeExpenseDetailsDO::getDeleted, false)
.likeIfPresent(IncomeExpenseDetailsDO::getBusinessNo, pageReqVO.getBusinessNo())
.likeIfPresent(IncomeExpenseDetailsDO::getOrderNo, pageReqVO.getOrderNo())
.betweenIfPresent(IncomeExpenseDetailsDO::getCreateTime, pageReqVO.getCreateTime())
.eqIfPresent(IncomeExpenseDetailsDO::getIncomeExpenseType, pageReqVO.getIncomeExpenseType())
.eqIfPresent(IncomeExpenseDetailsDO::getTradeType, pageReqVO.getTradeType())
.eqIfPresent(IncomeExpenseDetailsDO::getCashAmountChange, pageReqVO.getRechargeAmount())
.eqIfPresent(IncomeExpenseDetailsDO::getGiftAmountChange, pageReqVO.getGiftAmount())
.orderByDesc(IncomeExpenseDetailsDO::getId);
Integer tradeType = pageReqVO.getTradeType();
// 如果查的是交易,需要包含手工调账
if (ObjectUtil.isNotNull(tradeType) && TradeTypeEnum.RECHARGE.getCode().equals(tradeType)) {
queryWrapperX.in(IncomeExpenseDetailsDO::getTradeType, TradeTypeEnum.RECHARGE.getCode(), TradeTypeEnum.MANUAL_ADJUST.getCode());
} else {
queryWrapperX.eqIfPresent(IncomeExpenseDetailsDO::getTradeType, tradeType);
}
return selectPage(pageReqVO, queryWrapperX);
}
/**
* 账户明细分页查询
*
* @param page
* @param reqVO
* @return
*/
IPage<AccountDetailsDO> getAccountDetailsPage(@Param("page") IPage<AccountDetailsDO> page, @Param("reqVO") BalanceDetailsPageReqVO reqVO);
/**
* 获取手工调账分页
*
* @param pageReqVO
* @return
*/
default PageResult<IncomeExpenseDetailsDO> selectAdjustPage(ManualAdjustAccountBalancePageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<IncomeExpenseDetailsDO>()
.eq(IncomeExpenseDetailsDO::getTradeType, TradeTypeEnum.MANUAL_ADJUST.getCode())
.eqIfPresent(IncomeExpenseDetailsDO::getIncomeExpenseType, AdjustTypeEnum.getIncomeExpenseType(pageReqVO.getAdjustType()))
.eqIfPresent(IncomeExpenseDetailsDO::getOrganId, pageReqVO.getOrganId())
.betweenIfPresent(IncomeExpenseDetailsDO::getCreateTime, pageReqVO.getCreateTime())
.likeIfPresent(IncomeExpenseDetailsDO::getRemark, pageReqVO.getRemark())
.orderByDesc(IncomeExpenseDetailsDO::getId)
);
}
}
@@ -1,55 +0,0 @@
package com.cf.imes.module.system.enums.pay;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 手工调账类型枚举
*
* @author Gqr
* @since 2025/9/16 10:41
*/
@Getter
@AllArgsConstructor
public enum AdjustTypeEnum {
/**
* 调增
*/
INCREASE(0),
/**
* 调减
*/
DECREASE(1);
private final Integer type;
public static AdjustTypeEnum getByType(Integer type) {
for (AdjustTypeEnum value : AdjustTypeEnum.values()) {
if (value.getType().equals(type)) {
return value;
}
}
return null;
}
/**
* 从调账类型获取收支明细类型
*
* @param type
* @return
*/
public static Integer getIncomeExpenseType(Integer type) {
AdjustTypeEnum adjustType = getByType(type);
if (adjustType == null) {
return null;
}
if (adjustType.equals(INCREASE)) {
return IncomeExpenseTypeEnum.INCOME.getCode();
}
if (adjustType.equals(DECREASE)) {
return IncomeExpenseTypeEnum.EXPENSES.getCode();
}
return null;
}
}
@@ -49,24 +49,4 @@ public enum IncomeExpenseTypeEnum implements BaseEnum {
return null;
}
/**
* 从收支明细类型获取调账类型
*
* @param type
* @return
*/
public static Integer getAdjustType(Integer type) {
IncomeExpenseTypeEnum incomeExpenseTypeEnum = fromType(type);
if (incomeExpenseTypeEnum == null) {
return null;
}
if (incomeExpenseTypeEnum.equals(INCOME)) {
return AdjustTypeEnum.INCREASE.getType();
}
if (incomeExpenseTypeEnum.equals(EXPENSES)) {
return AdjustTypeEnum.DECREASE.getType();
}
return null;
}
}
@@ -1,5 +1,6 @@
package com.cf.imes.module.system.enums.pay;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.AllArgsConstructor;
@@ -21,12 +22,7 @@ public enum PayChannelCodeEnum {
/**
* 微信
*/
WECHAT_NATIVE(1, "微信"),
/**
* 手工调账
*/
MANUAL_ADJUST(2, "手工调账");
WECHAT_NATIVE(1, "微信");
@EnumValue
private final Integer code;
@@ -62,4 +58,20 @@ public enum PayChannelCodeEnum {
public static boolean isWechat(Integer type) {
return WECHAT_NATIVE.code.equals(type);
}
/**
* 返回可读描述,比如“现金+微信”
*
* @param code
*/
public static String describe(Integer code) {
if (ObjectUtil.isNull(code)) {
return null;
}
PayChannelCodeEnum channelCodeEnum = fromType(code);
if (ObjectUtil.isNull(channelCodeEnum)) {
return null;
}
return channelCodeEnum.getDesc();
}
}
@@ -1,137 +0,0 @@
package com.cf.imes.module.system.enums.pay;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author Gqr
* @since 2025/10/16 11:58
*/
@Getter
public enum PayProductChannelCodeEnumNew {
/**
* 现金
*/
BALANCE(1, "现金"), // 二进制 0001
/**
* 赠送金
*/
GIFT(1 << 1, "赠送金"), // 二进制 0010
/**
* 支付宝
*/
ALIPAY(1 << 2, "支付宝"), // 二进制 0100
/**
* 微信
*/
WECHAT(1 << 3, "微信"); // 二进制 1000
private final int code;
private final String label;
PayProductChannelCodeEnumNew(int code, String label) {
this.code = code;
this.label = label;
}
/**
* 把多个支付方式组合成一个整数
*
* @param types
*/
public static int combine(PayProductChannelCodeEnumNew... types) {
int result = 0;
for (PayProductChannelCodeEnumNew type : types) {
result |= type.code;
}
return result;
}
/**
* 是否包含现金
*/
public static boolean hasBalance(int code) {
return (code & PayProductChannelCodeEnumNew.BALANCE.getCode()) != 0;
}
/**
* 是否只有现金
*/
public static boolean isBalanceOnly(int code) {
return code == BALANCE.code;
}
/**
* 是否是现金+赠送金
*/
public static boolean isBalanceAndGift(int code) {
return code == combine(BALANCE, GIFT);
}
/**
* 是否包含赠送金
*/
public static boolean hasGift(int code) {
return (code & PayProductChannelCodeEnumNew.GIFT.getCode()) != 0;
}
/**
* 是否只有赠送金
*/
public static boolean isGiftOnly(int code) {
return code == GIFT.code;
}
/**
* 是否包含支付宝
*/
public static boolean hasAlipay(int code) {
return (code & PayProductChannelCodeEnumNew.ALIPAY.getCode()) != 0;
}
/**
* 是否包含微信
*/
public static boolean hasWechat(int code) {
return (code & PayProductChannelCodeEnumNew.WECHAT.getCode()) != 0;
}
/**
* 获取所有包含的支付方式列表
*/
public static List<PayProductChannelCodeEnumNew> parse(int code) {
List<PayProductChannelCodeEnumNew> list = new ArrayList<>();
for (PayProductChannelCodeEnumNew type : PayProductChannelCodeEnumNew.values()) {
if ((code & type.getCode()) != 0) {
list.add(type);
}
}
return list;
}
/**
* 返回可读描述,比如“现金+微信”
*
* @param code
*/
public static String describe(Integer code) {
if (ObjectUtil.isNull(code)) {
return null;
}
List<PayProductChannelCodeEnumNew> parse = parse(code);
if (CollUtil.isEmpty(parse)) {
return null;
}
return parse.stream()
.map(PayProductChannelCodeEnumNew::getLabel)
.collect(Collectors.joining("+"));
}
}
@@ -13,20 +13,11 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public enum TradeTypeEnum implements BaseEnum {
/**
* 充值
*/
RECHARGE(0, "充值"),
/**
* 产品购买
*/
PRODUCT(1, "产品购买"),
/**
* 手工调账
*/
MANUAL_ADJUST(2, "手工调账");
PRODUCT(1, "产品购买");
private final Integer code;
@@ -41,16 +32,6 @@ public enum TradeTypeEnum implements BaseEnum {
return null;
}
/**
* 是否充值
*
* @param code
* @return
*/
public static boolean isRecharge(Integer code) {
return RECHARGE.getCode().equals(code);
}
/**
* 是否产品购买
*
@@ -67,6 +48,6 @@ public enum TradeTypeEnum implements BaseEnum {
* @return
*/
public static TradeTypeEnum[] validArr() {
return new TradeTypeEnum[]{RECHARGE, PRODUCT};
return new TradeTypeEnum[]{PRODUCT};
}
}
@@ -1,9 +1,5 @@
package com.cf.imes.module.system.service.funds.incomeandexpense;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.balancedetails.vo.BalanceDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.balancedetails.vo.BalanceDetailsRespVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
/**
@@ -19,20 +15,4 @@ public interface IncomeExpenseService {
* @param incomeExpenseDetailsDO
*/
Long createDetail(IncomeExpenseDetailsDO incomeExpenseDetailsDO);
/**
* 查询余额明细分页
*
* @param pageReqVO
* @return
*/
PageResult<BalanceDetailsRespVO> getBalanceDetailsPage(BalanceDetailsPageReqVO pageReqVO);
/**
* 获取手工调账分页
*
* @param pageReqVO
* @return
*/
PageResult<IncomeExpenseDetailsDO> selectAdjustPage(ManualAdjustAccountBalancePageReqVO pageReqVO);
}
@@ -1,30 +1,11 @@
package com.cf.imes.module.system.service.funds.incomeandexpense;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.balancedetails.vo.BalanceDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.balancedetails.vo.BalanceDetailsRespVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.AccountDetailsDO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.dal.mysql.incomeandexpense.IncomeExpenseDetailsMapper;
import com.cf.imes.module.system.enums.pay.PayProductChannelCodeEnumNew;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
import com.cf.imes.module.system.service.organ.OrganService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
/**
* 收支明细接口实现类
*
@@ -44,74 +25,4 @@ public class IncomeExpenseServiceImpl implements IncomeExpenseService {
incomeExpenseDetailsMapper.insert(incomeExpenseDetailsDO);
return incomeExpenseDetailsDO.getId();
}
@Override
public PageResult<BalanceDetailsRespVO> getBalanceDetailsPage(BalanceDetailsPageReqVO pageReqVO) {
// 时间类型规范为开始0点,结束12点
LocalDate[] createTime = pageReqVO.getCreateTime();
if (ArrayUtil.isNotEmpty(createTime) && createTime.length == 2) {
pageReqVO.setOperateTime(new LocalDateTime[]{
pageReqVO.getCreateTime()[0].atStartOfDay(),
pageReqVO.getCreateTime()[1].atTime(LocalTime.MAX)
});
} else {
pageReqVO.setOperateTime(null);
}
PageDTO<AccountDetailsDO> page = new PageDTO<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
IPage<AccountDetailsDO> pageResult = incomeExpenseDetailsMapper.getAccountDetailsPage(page, pageReqVO);
List<AccountDetailsDO> pageResultList = pageResult.getRecords();
if(CollUtil.isEmpty(pageResultList)){
return new PageResult<>();
}
List<BalanceDetailsRespVO> resultList = new ArrayList<>();
// 遍历构造结果
pageResultList.forEach(i -> {
BalanceDetailsRespVO respVO = new BalanceDetailsRespVO();
respVO.setBusinessNo(i.getBusinessNo());
respVO.setCreator(i.getCreator());
respVO.setCreateTime(i.getCreateTime());
respVO.setIncomeExpenseType(i.getIncomeExpenseType());
// 根据交易类型赋值对应的 金额字段
Integer tradeType = i.getTradeType();
respVO.setTradeType(tradeType);
if (TradeTypeEnum.RECHARGE.getCode().equals(tradeType)) {
respVO.setRechargeAmount(i.getCashAmountChange());
respVO.setRechargeGiftAmount(i.getGiftAmountChange());
respVO.setPaymentMethod(ObjectUtil.isNotNull(i.getChannelCode()) ? i.getChannelCode().getDesc() : null);
respVO.setOrderNo(i.getOrderNo());
} else if (TradeTypeEnum.PRODUCT.getCode().equals(tradeType)) {
respVO.setProductPrice(i.getTotalAmount());
respVO.setBalancePayAmount(i.getAccountBalanceSpent());
respVO.setRechargePayAmount(i.getExternalSpent());
respVO.setGiftPayAmount(i.getGiftMoneySpent());
respVO.setPaymentMethod(PayProductChannelCodeEnumNew.describe(i.getPaymentMethod()));
respVO.setOrderNo(ObjectUtil.isNotNull(i.getPurchaseId()) ? String.valueOf(i.getPurchaseId()) : null);
} else if (TradeTypeEnum.MANUAL_ADJUST.getCode().equals(tradeType)) {
respVO.setRechargeAmount(i.getCashAmountChange());
respVO.setRechargeGiftAmount(i.getGiftAmountChange());
// 手工调账算到充值
respVO.setTradeType(TradeTypeEnum.RECHARGE.getCode());
respVO.setPaymentMethod(TradeTypeEnum.MANUAL_ADJUST.getDesc());
respVO.setOrderNo(i.getOrderNo());
}
// 查询操作组织名
OrganizationDO organ = organService.getOrganWithDeleted(i.getOrganId());
if (ObjectUtil.isNotNull(organ)) {
respVO.setOrganName(organ.getName());
}
resultList.add(respVO);
});
return new PageResult<>(resultList, pageResult.getTotal());
}
@Override
public PageResult<IncomeExpenseDetailsDO> selectAdjustPage(ManualAdjustAccountBalancePageReqVO pageReqVO) {
return incomeExpenseDetailsMapper.selectAdjustPage(pageReqVO);
}
}
}
@@ -210,7 +210,7 @@ public class InvoiceServiceImpl implements InvoiceService {
availablePageRespVO.setCreateTime(i.getCreateTime());
availablePageRespVO.setTradeType(TradeTypeEnum.PRODUCT.getCode());
// 可开票金额=余额支付+扫码支付
availablePageRespVO.setAvailableAmount(i.getAccountBalanceSpent().add(i.getExternalSpent()));
availablePageRespVO.setAvailableAmount((i.getExternalSpent()));
availablePageRespVO.setProductName(i.getProductName());
availablePageRespVO.setTotalAmount(i.getTotalAmount());
availablePageRespVOS.add(availablePageRespVO);
@@ -307,7 +307,7 @@ public class InvoiceServiceImpl implements InvoiceService {
invoicePurchaseRecord.setPurchaseRecordId(purchaseRecordDO.getId());
invoicePurchaseRecord.setProductName(purchaseRecordDO.getProductName());
invoicePurchaseRecord.setTradeType(TradeTypeEnum.PRODUCT.getCode());
invoicePurchaseRecord.setInvoicableAmount(purchaseRecordDO.getTotalAmount().subtract(purchaseRecordDO.getGiftMoneySpent()));
invoicePurchaseRecord.setInvoicableAmount(purchaseRecordDO.getTotalAmount());
invoicePurchaseRecord.setTotalAmount(purchaseRecordDO.getTotalAmount());
invoicePurchaseRecord.setCreateTime(purchaseRecordDO.getCreateTime());
invoicePurchaseRecords.add(invoicePurchaseRecord);
@@ -1,30 +0,0 @@
package com.cf.imes.module.system.service.funds.manualadjust;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceRespVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceSaveReqVO;
/**
* 手动调账 Service 接口
*
* @author Gqr
* @since 2025/9/16 10:23
*/
public interface ManualAdjustAccountBalanceService {
/**
* 创建调账
*
* @param saveReqVO
* @return
*/
Long createAjustment(ManualAdjustAccountBalanceSaveReqVO saveReqVO);
/**
* 获取手工调账分页
*
* @param pageReqVO
* @return
*/
PageResult<ManualAdjustAccountBalanceRespVO> getPage(ManualAdjustAccountBalancePageReqVO pageReqVO);
}
@@ -1,180 +0,0 @@
package com.cf.imes.module.system.service.funds.manualadjust;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.id.core.util.SnowflakeSerialNoWorker3rd;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceRespVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceSaveReqVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganRechargeAmountRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.organamount.OrganAmountDO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderDO;
import com.cf.imes.module.system.enums.pay.AdjustTypeEnum;
import com.cf.imes.module.system.enums.pay.IncomeExpenseTypeEnum;
import com.cf.imes.module.system.enums.pay.PayChannelCodeEnum;
import com.cf.imes.module.system.enums.pay.PayOrderStatusEnum;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
import com.cf.imes.module.system.framework.snowflake.config.MybatisIdProperties;
import com.cf.imes.module.system.service.funds.incomeandexpense.IncomeExpenseService;
import com.cf.imes.module.system.service.funds.organamount.OrganAmountService;
import com.cf.imes.module.system.service.organ.OrganService;
import com.cf.imes.module.system.service.pay.PayOrderService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAMOUNT_GIFT_INSUFFICIENT_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAMOUNT_RECHARGE_INSUFFICIENT_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.RECHARGE_GIFT_MEANWHILE_EMPTY_ERROR;
/**
* 手动调账 ServiceImpl 接口实现类
*
* @author Gqr
* @since 2025/9/16 10:24
*/
@Service
public class ManualAdjustAccountBalanceServiceImpl implements ManualAdjustAccountBalanceService {
@Resource
private OrganService organService;
@Resource
private OrganAmountService organAmountService;
@Resource
private IncomeExpenseService incomeExpenseService;
@Resource
private MybatisIdProperties mybatisIdProperties;
@Resource
private PayOrderService payOrderService;
@Resource
private SnowflakeSerialNoWorker3rd snowflakeSerialNoWorker3rd;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createAjustment(ManualAdjustAccountBalanceSaveReqVO saveReqVO) {
// 校验金额同时为空
BigDecimal rechargeAmount = saveReqVO.getRechargeAmount();
BigDecimal giftAmount = saveReqVO.getGiftAmount();
AssertUtils.equals(ObjectUtil.isAllEmpty(rechargeAmount, giftAmount), true, RECHARGE_GIFT_MEANWHILE_EMPTY_ERROR);
Long organId = saveReqVO.getOrganId();
// 校验组织
organService.validOrgan(organId);
// 校验组织套餐
OrganAmountDO organAmountDO = organAmountService.validOrganAmount(organId);
Integer incomeExpenseType = IncomeExpenseTypeEnum.INCOME.getCode();
OrganRechargeAmountRespVO rechargeRespVO = new OrganRechargeAmountRespVO();;
switch (AdjustTypeEnum.getByType(saveReqVO.getAdjustType())) {
case INCREASE:
// 调增直接累加
rechargeRespVO = organAmountService.recharge(organId, rechargeAmount, giftAmount);
break;
case DECREASE:
incomeExpenseType = IncomeExpenseTypeEnum.EXPENSES.getCode();
// 调减需要先判断余额跟赠送金够不够减
if (ObjectUtil.isNotNull(rechargeAmount)) {
if (organAmountDO.getAmount().compareTo(rechargeAmount) < 0) {
throw exception(ORGAMOUNT_RECHARGE_INSUFFICIENT_ERROR);
}
// 反转为负数
rechargeAmount = rechargeAmount.negate();
}
if (ObjectUtil.isNotNull(giftAmount)) {
if (organAmountDO.getGiftAmount().compareTo(giftAmount) < 0) {
throw exception(ORGAMOUNT_GIFT_INSUFFICIENT_ERROR);
}
// 反转为负数
giftAmount = giftAmount.negate();
}
rechargeRespVO = organAmountService.recharge(organId, rechargeAmount, giftAmount);
break;
default:
break;
}
// 新增支付单
String payOrderId = null;
if (ObjectUtil.isNotNull(rechargeAmount)) {
PayOrderDO payOrderDO = createPayOrder(organId, rechargeAmount);
payOrderService.createPayOrder(payOrderDO);
payOrderId = String.valueOf(payOrderDO.getId());
}
// 新增收支明细
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.orderNo(String.valueOf(payOrderId))
.tradeType(TradeTypeEnum.MANUAL_ADJUST.getCode())
.incomeExpenseType(incomeExpenseType)
.cashAmountChange(rechargeAmount)
.giftAmountChange(giftAmount)
.availableAmount(rechargeRespVO.getAvailableAmount())
.amount(rechargeRespVO.getAmount())
.giftAmount(rechargeRespVO.getGiftAmount())
.remark(saveReqVO.getRemark())
.build();
return incomeExpenseService.createDetail(incomeExpenseDetailsDO);
}
/**
* 创建支付订单
*
* @param
* @return
*/
private PayOrderDO createPayOrder(Long organId, BigDecimal recharge) {
PayOrderDO payOrderDO = new PayOrderDO();
Long payOrderId = IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId();
payOrderDO.setId(payOrderId);
payOrderDO.setStatus(PayOrderStatusEnum.SUCCESS);
payOrderDO.setPrice(recharge);
payOrderDO.setSubject("手工调账");
payOrderDO.setChannelCode(PayChannelCodeEnum.MANUAL_ADJUST);
payOrderDO.setOrganId(organId);
return payOrderDO;
}
@Override
public PageResult<ManualAdjustAccountBalanceRespVO> getPage(ManualAdjustAccountBalancePageReqVO pageReqVO) {
// 时间类型规范为开始0点,结束12点
pageReqVO.setCreateTime(LocalDateTimeUtils.generateTimeSection(pageReqVO.getCreateTime()));
PageResult<IncomeExpenseDetailsDO> incomeExpenseDetailsDOPageResult = incomeExpenseService.selectAdjustPage(pageReqVO);
List<IncomeExpenseDetailsDO> pageResultList = incomeExpenseDetailsDOPageResult.getList();
List<ManualAdjustAccountBalanceRespVO> resultList = new ArrayList<>();
for (IncomeExpenseDetailsDO detailsDO : pageResultList) {
ManualAdjustAccountBalanceRespVO respVO = BeanUtils.toBean(detailsDO, ManualAdjustAccountBalanceRespVO.class);
// 从收支类型转调账类型
respVO.setAdjustType(IncomeExpenseTypeEnum.getAdjustType(detailsDO.getIncomeExpenseType()));
// 查询操作组织名
OrganizationDO organ = organService.getOrganWithDeleted(detailsDO.getOrganId());
if (ObjectUtil.isNotNull(organ)) {
respVO.setOrganName(organ.getName());
}
resultList.add(respVO);
}
return new PageResult<>(resultList, incomeExpenseDetailsDOPageResult.getTotal());
}
}
@@ -1,13 +1,8 @@
package com.cf.imes.module.system.service.funds.organamount;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.ManageAmountOverviewRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAvailableAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganFundsStatisticsReqVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganRechargeAmountRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.organamount.OrganAmountDO;
import java.math.BigDecimal;
import java.util.Map;
/**
@@ -15,62 +10,6 @@ import java.util.Map;
*/
public interface OrganAmountService {
/**
* 校验机构套餐
*
* @param organId
*/
OrganAmountDO validOrganAmount(Long organId);
/**
* 机构充值
*
* @param organId
* @param amount 充值金额
* @param gift 赠送金额
* @return
*/
OrganRechargeAmountRespVO recharge(Long organId, BigDecimal amount, BigDecimal gift);
/**
* 组织购买产品
*
* @param organAmountDO
* @return
*/
void productPay(OrganAmountDO organAmountDO);
/**
* 产品外部支付失败更新余额/赠送金
*
* @param organId
* @param balance
* @param gift
*/
OrganRechargeAmountRespVO refundProductOrganAmountBalanceAndGift(Long organId, BigDecimal balance, BigDecimal gift);
/**
* 获取组织余额数据
*
* @return
*/
OrganAmountRespVO getOrganAmount();
/**
* 获取组织可用金额信息
*
* @return
*/
OrganAvailableAmountRespVO getOrganAvailableAmount();
/**
* 管理端获取可用金额信息
*
* @param organId 组织id
* @return
*/
OrganAvailableAmountRespVO getManageAvailableAmount(Long organId);
/**
* 获取全部组织的余额数据
*
@@ -86,9 +25,4 @@ public interface OrganAmountService {
* @return
*/
Map<String, Object> getConsumptionTrend(OrganFundsStatisticsReqVO reqVO, boolean queryOrg);
/**
* 修正组织余额,遍历组织列表,补充system_organization_amount数据
*/
void fixOrganAmount();
}
@@ -1,28 +1,12 @@
package com.cf.imes.module.system.service.funds.organamount;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.ManageAmountOverviewRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAmountGroupByCreateTimeRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAvailableAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganFundsStatisticsReqVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganRechargeAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.dal.mysql.organ.OrganMapper;
import com.cf.imes.module.system.service.funds.invoice.InvoiceService;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.OrgEarliestPurchaseProductRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.organamount.OrganAmountDO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import com.cf.imes.module.system.dal.mysql.funds.organamount.OrganAmountMapper;
import com.cf.imes.module.system.service.organ.OrganService;
import lombok.extern.slf4j.Slf4j;
@@ -39,15 +23,10 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;
import static com.cf.imes.framework.common.constants.StatisticsConstants.DATELIST_FIELD_NAME;
import static com.cf.imes.framework.common.constants.StatisticsConstants.SERIES_FIELD_NAME;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.common.util.time.StatisticsChangeUtils.generateDateRangeAxis;
import static com.cf.imes.framework.common.util.time.StatisticsChangeUtils.getDateList;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAN_AMOUNT_NO_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAN_PRODUCT_PAY_AMOUNT_CHANGE_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAN_RECHARGE_AMOUNT_UPDATE_ERROR;
/**
* @author 资金管理接口 实现类
@@ -69,160 +48,6 @@ public class OrganAmountServiceImpl implements OrganAmountService {
@Resource
private PurchaseService purchaseService;
@Resource
private OrganMapper organMapper;
@Override
public OrganAmountDO validOrganAmount(Long organId) {
OrganAmountDO organAmountDO = organAmountMapper.selectOne(new LambdaQueryWrapper<OrganAmountDO>().eq(OrganAmountDO::getOrganId, organId));
AssertUtils.notEmpty(organAmountDO, ORGAN_AMOUNT_NO_EXIST);
return organAmountDO;
}
@Override
public OrganRechargeAmountRespVO recharge(Long organId, BigDecimal price, BigDecimal gift) {
OrganAmountDO organAmountDO = validOrganAmount(organId);
BigDecimal newAmount = organAmountDO.getAmount();
if (ObjectUtil.isNotNull(price)) {
newAmount = organAmountDO.getAmount().add(price);
}
BigDecimal newGift = organAmountDO.getGiftAmount();
if (ObjectUtil.isNotNull(gift)) {
newGift = organAmountDO.getGiftAmount().add(gift);
}
int updated = organAmountMapper.update(new LambdaUpdateWrapperX<OrganAmountDO>()
.eq(OrganAmountDO::getOrganId, organId)
.eq(OrganAmountDO::getVersion, organAmountDO.getVersion())
.set(OrganAmountDO::getGiftAmount, newGift)
.set(OrganAmountDO::getAmount, newAmount)
.set(OrganAmountDO::getVersion, organAmountDO.getVersion() + 1));
// 1. 首次更新失败,认为出现并发,再查一次再更新
if (updated == 0) {
organAmountDO = organAmountMapper.selectOne(new LambdaQueryWrapper<OrganAmountDO>().eq(OrganAmountDO::getOrganId, organId));
newAmount = organAmountDO.getAmount().add(price);
newGift = organAmountDO.getGiftAmount().add(gift);
updated = organAmountMapper.update(new LambdaUpdateWrapperX<OrganAmountDO>()
.eq(OrganAmountDO::getOrganId, organId)
.eq(OrganAmountDO::getVersion, organAmountDO.getVersion())
.set(OrganAmountDO::getGiftAmount, newGift)
.set(OrganAmountDO::getAmount, newAmount)
.set(OrganAmountDO::getVersion, organAmountDO.getVersion() + 1));
// 2. 第二次更新失败,资金表可能不存在
if (updated == 0) {
throw exception(ORGAN_RECHARGE_AMOUNT_UPDATE_ERROR);
} else {
return new OrganRechargeAmountRespVO(newAmount.add(newGift), newAmount, newGift);
}
} else {
return new OrganRechargeAmountRespVO(newAmount.add(newGift), newAmount, newGift);
}
}
@Override
public void productPay(OrganAmountDO organAmountDO) {
int updated = organAmountMapper.update(new LambdaUpdateWrapper<OrganAmountDO>()
.eq(OrganAmountDO::getOrganId, organAmountDO.getOrganId())
.eq(OrganAmountDO::getVersion, organAmountDO.getVersion())
.set(OrganAmountDO::getAmount, organAmountDO.getAmount())
.set(OrganAmountDO::getGiftAmount, organAmountDO.getGiftAmount())
.set(OrganAmountDO::getVersion, organAmountDO.getVersion() + 1));
if (updated == 0) {
throw new ServiceException(ORGAN_PRODUCT_PAY_AMOUNT_CHANGE_ERROR);
}
}
@Override
public OrganRechargeAmountRespVO refundProductOrganAmountBalanceAndGift(Long organId, BigDecimal balance, BigDecimal gift) {
OrganAmountDO organAmountDO = organAmountMapper.selectOne(new LambdaQueryWrapper<OrganAmountDO>().eq(OrganAmountDO::getOrganId, organId));
BigDecimal newAmount = organAmountDO.getAmount().add(balance);
BigDecimal newGift = organAmountDO.getGiftAmount().add(gift);
int updated = organAmountMapper.update(new LambdaUpdateWrapper<OrganAmountDO>()
.eq(OrganAmountDO::getOrganId, organId)
.eq(OrganAmountDO::getVersion, organAmountDO.getVersion())
.set(OrganAmountDO::getAmount, newAmount)
.set(OrganAmountDO::getGiftAmount, newGift)
.set(OrganAmountDO::getVersion, organAmountDO.getVersion() + 1));
// 1. 首次更新失败,认为出现并发,再查一次再更新
if (updated == 0) {
organAmountDO = organAmountMapper.selectOne(new LambdaQueryWrapper<OrganAmountDO>().eq(OrganAmountDO::getOrganId, organId));
newAmount = organAmountDO.getAmount().add(balance);
newGift = organAmountDO.getGiftAmount().add(gift);
updated = organAmountMapper.update(new LambdaUpdateWrapper<OrganAmountDO>()
.eq(OrganAmountDO::getOrganId, organId)
.eq(OrganAmountDO::getVersion, organAmountDO.getVersion())
.set(OrganAmountDO::getAmount, newAmount)
.set(OrganAmountDO::getGiftAmount, newGift)
.set(OrganAmountDO::getVersion, organAmountDO.getVersion() + 1));
// 2. 第二次更新失败,资金表可能不存在
if (updated == 0) {
throw exception(ORGAN_RECHARGE_AMOUNT_UPDATE_ERROR);
} else {
return new OrganRechargeAmountRespVO(newAmount.add(newGift), newAmount, newGift);
}
} else {
return new OrganRechargeAmountRespVO(newAmount.add(newGift), newAmount, newGift);
}
}
@Override
public OrganAmountRespVO getOrganAmount() {
Long organId = SecurityFrameworkUtils.getUserOrganId();
organService.validOrgan(organId);
OrganAmountDO organAmountDO = validOrganAmount(organId);
OrganAmountRespVO organAmountRespVO = BeanUtils.toBean(organAmountDO, OrganAmountRespVO.class);
// 查询组织最晚还有效的产品购买记录
OrgEarliestPurchaseProductRespVO orgEarliestProductDetail = purchaseService.getOrgEarliestProductDetail(organId);
if (ObjectUtil.isNotNull(orgEarliestProductDetail)) {
// 查询对应购买记录
PurchaseRecordDO purchaseRecordDO = orgEarliestProductDetail.getPurchaseRecordDO();
organAmountRespVO.setProductEfficientDate(LocalDateTimeUtil.format(purchaseRecordDO.getEndTime(), NORM_DATETIME_FORMATTER));
// 首购记录不展示时长
if (!purchaseRecordDO.getInitial()) {
organAmountRespVO.setDuration(purchaseRecordDO.getPurchaseDuration());
organAmountRespVO.setDurationUnit(purchaseRecordDO.getPurchaseDurationUnit());
}
}
// 查询可开票金额
organAmountRespVO.setInvoiceableAmount(purchaseService.getInvoicingAmount(organId));
return organAmountRespVO;
}
@Override
public OrganAvailableAmountRespVO getOrganAvailableAmount() {
Long organId = SecurityFrameworkUtils.getUserOrganId();
organService.validOrgan(organId);
OrganAmountDO organAmountDO = validOrganAmount(organId);
return BeanUtils.toBean(organAmountDO, OrganAvailableAmountRespVO.class);
}
@Override
public OrganAvailableAmountRespVO getManageAvailableAmount(Long organId) {
// 查询固定组织的可用金额
if (ObjectUtil.isNotNull(organId)) {
organService.getOrganWithDeleted(organId);
OrganAmountDO organAmountDO = validOrganAmount(organId);
return BeanUtils.toBean(organAmountDO, OrganAvailableAmountRespVO.class);
}
// 查询所有组织的可用金额
return organAmountMapper.getTotalAvailableAmount();
}
@Override
public ManageAmountOverviewRespVO getOrganAmountAll() {
ManageAmountOverviewRespVO respVO = new ManageAmountOverviewRespVO();
@@ -230,9 +55,6 @@ public class OrganAmountServiceImpl implements OrganAmountService {
TotalSalesAmountRespVO totalSales = purchaseService.getTotalSales();
// 销售总额
respVO.setTotalSalesAmount(totalSales.getAmount());
respVO.setTotalSalesGiftAmount(totalSales.getGiftAmount());
// 充值余额
respVO.setRechargeBalance(organAmountMapper.getTotalRechargeAmount());
// 可开票金额
respVO.setToExamineAmount(invoiceService.getManageInvoiceAmount().getPendingInvoice());
@@ -274,20 +96,4 @@ public class OrganAmountServiceImpl implements OrganAmountService {
return resultMap;
}
@Override
public void fixOrganAmount() {
List<OrganizationDO> organizationDOS = organMapper.selectList(new LambdaQueryWrapper<OrganizationDO>().select(OrganizationDO::getId));
log.info("[fixOrganAmount][开始修正组织资金账户,组织总数({})]", organizationDOS.size());
for (OrganizationDO organ : organizationDOS) {
Long organId = organ.getId();
OrganAmountDO organAmountDO = organAmountMapper.selectOne(new LambdaQueryWrapper<OrganAmountDO>().eq(OrganAmountDO::getOrganId, organId));
if (ObjectUtil.isNull(organAmountDO)) {
// 组织没有资金账户,新增一个
organAmountMapper.insert(OrganAmountDO.builder()
.organId(organId)
.build());
}
}
}
}
@@ -0,0 +1,62 @@
package com.cf.imes.module.system.service.funds.productpromotion;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.productpromotion.ProductPromotionDO;
import jakarta.validation.Valid;
import java.util.List;
/**
* 优惠活动表 product_promotion Service 接口
*
* @author 晨丰科技
*/
public interface ProductPromotionService {
/**
* 创建优惠活动
*
* @param createReqVO
* @return 编号
*/
Long create(@Valid ProductPromotionSaveReqVO createReqVO);
/**
* 更新优惠活动
*
* @param updateReqVO 更新信息
*/
void update(@Valid ProductPromotionSaveReqVO updateReqVO);
/**
* 删除优惠活动
*
* @param id 编号
*/
void delete(Long id);
/**
* 获得优惠活动
*
* @param id 编号
*/
ProductPromotionDO get(Long id);
/**
* 获得优惠活动 分页
*
* @param pageReqVO 分页查询
*/
PageResult<ProductPromotionDO> getPage(ProductPromotionPageReqVO pageReqVO);
/**
* 获取可用优惠活动
*
* @param productId
* @return
*/
List<ProductPromotionDO> getAvailableProductPromotionList(Long productId);
}
@@ -0,0 +1,154 @@
package com.cf.imes.module.system.service.funds.productpromotion;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.productpromotion.ProductPromotionDO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO;
import com.cf.imes.module.system.dal.mysql.funds.productpromotion.ProductPromotionMapper;
import com.cf.imes.module.system.enums.pay.DurationUnitEnum;
import com.cf.imes.module.system.service.funds.products.ProductsDetailService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCT_PROMOTION_ACTIVE_NAME_IS_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCT_PROMOTION_NO_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST;
/**
* 优惠活动表 product_promotion Service 实现类
*
* @author 晨丰科技
*/
@Service
@Validated
public class ProductPromotionServiceImpl implements ProductPromotionService {
@Resource
private ProductPromotionMapper productPromotionMapper;
@Resource
private ProductsDetailService productsDetailService;
@Override
public Long create(ProductPromotionSaveReqVO createReqVO) {
Long productId = createReqVO.getProductId();
ProductsDO productsDO = productsDetailService.validateProductExist(productId);
// 校验活动名称唯一
ProductPromotionDO productPromotionDO = productPromotionMapper.selectOne(new LambdaQueryWrapperX<ProductPromotionDO>()
.eq(ProductPromotionDO::getDeleted, false)
.eq(ProductPromotionDO::getActivityName, createReqVO.getActivityName()));
AssertUtils.empty(productPromotionDO, PRODUCT_PROMOTION_ACTIVE_NAME_IS_EXIST);
// 校验对应产品购买时长唯一
productPromotionDO = productPromotionMapper.selectOne(new LambdaQueryWrapperX<ProductPromotionDO>()
.eq(ProductPromotionDO::getDeleted, false)
.eq(ProductPromotionDO::getPurchaseDuration, createReqVO.getPurchaseDuration())
.eq(ProductPromotionDO::getPurchaseDurationUnit, createReqVO.getPurchaseDurationUnit())
.eq(ProductPromotionDO::getProductId, productId));
AssertUtils.empty(productPromotionDO, PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST, createReqVO.getPurchaseDuration(), DurationUnitEnum.getDesc(createReqVO.getPurchaseDurationUnit()));
ProductPromotionDO promotionDO = BeanUtils.toBean(createReqVO, ProductPromotionDO.class);
productPromotionDO.setProductId(productsDO.getId());
productPromotionDO.setProductName(productsDO.getProductName());
productPromotionMapper.insert(promotionDO);
return promotionDO.getId();
}
@Override
public void update(ProductPromotionSaveReqVO updateReqVO) {
Long productId = updateReqVO.getProductId();
ProductsDO productsDO = productsDetailService.validateProductExist(productId);
validateRechargeActiveExists(updateReqVO.getId());
// 校验活动名称唯一
ProductPromotionDO productPromotionDO = productPromotionMapper.selectOne(new LambdaQueryWrapperX<ProductPromotionDO>()
.eq(ProductPromotionDO::getDeleted, false)
.eq(ProductPromotionDO::getActivityName,updateReqVO.getActivityName())
.ne(ProductPromotionDO::getId,updateReqVO.getId()));
AssertUtils.empty(productPromotionDO, PRODUCT_PROMOTION_ACTIVE_NAME_IS_EXIST);
// 校验购买时长唯一
productPromotionDO = productPromotionMapper.selectOne(new LambdaQueryWrapperX<ProductPromotionDO>()
.eq(ProductPromotionDO::getDeleted, false)
.eq(ProductPromotionDO::getPurchaseDuration, updateReqVO.getPurchaseDuration())
.eq(ProductPromotionDO::getPurchaseDurationUnit, updateReqVO.getPurchaseDurationUnit())
.ne(ProductPromotionDO::getId, updateReqVO.getId())
.eq(ProductPromotionDO::getProductId, productId));
AssertUtils.empty(productPromotionDO, PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST, updateReqVO.getPurchaseDuration(), DurationUnitEnum.getDesc(updateReqVO.getPurchaseDurationUnit()));
ProductPromotionDO promotionDO = BeanUtils.toBean(updateReqVO, ProductPromotionDO.class);
productPromotionDO.setProductId(productsDO.getId());
productPromotionDO.setProductName(productsDO.getProductName());
productPromotionMapper.updateById(promotionDO);
}
@Override
public void delete(Long id) {
validateRechargeActiveExists(id);
productPromotionMapper.deleteById(id);
}
@Override
public ProductPromotionDO get(Long id) {
return validateRechargeActiveExists(id);
}
@Override
public PageResult<ProductPromotionDO> getPage(ProductPromotionPageReqVO pageReqVO) {
// 生成时间0点和止时间12点的区间
pageReqVO.setStartTime(LocalDateTimeUtils.generateTimeSection(pageReqVO.getStartTime()));
pageReqVO.setEndTime(LocalDateTimeUtils.generateTimeSection(pageReqVO.getEndTime()));
return productPromotionMapper.selectPage(pageReqVO);
}
@Override
public List<ProductPromotionDO> getAvailableProductPromotionList(Long productId) {
LocalDateTime now = LocalDateTime.now();
// 筛选掉投放时间还没到和过期的
return productPromotionMapper.selectList(new LambdaQueryWrapper<ProductPromotionDO>()
.eq(ProductPromotionDO::getDeleted, false)
.eq(ProductPromotionDO::getProductId, productId)
.le(ProductPromotionDO::getStartTime, now)
.ge(ProductPromotionDO::getEndTime, now)
);
}
// 校验是否存在
private ProductPromotionDO validateRechargeActiveExists(Long id) {
if (id == null) {
throw exception(PRODUCT_PROMOTION_NO_EXIST);
}
ProductPromotionDO giftMoneyDetailsDO = productPromotionMapper.selectOne(new LambdaQueryWrapperX<ProductPromotionDO>()
.eq(ProductPromotionDO::getId, id)
.eq(ProductPromotionDO::getDeleted, false));
if (giftMoneyDetailsDO == null) {
throw exception(PRODUCT_PROMOTION_NO_EXIST);
}
return giftMoneyDetailsDO;
}
}
@@ -3,7 +3,6 @@ package com.cf.imes.module.system.service.funds.purchase;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.OrgEarliestPurchaseProductRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailRespVO;
@@ -12,7 +11,6 @@ import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganCreateProd
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageSalesTotalStatisticRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
@@ -58,22 +56,6 @@ public interface PurchaseService {
*/
void updateRecordInvoicable(Long purchaseRecordId, Long organId);
/**
* 查询组织下最早购买产品定价规则
*
* @param organId
* @return
*/
OrgEarliestPurchaseProductRespVO getOrgEarliestProductDetail(Long organId);
/**
* 查询可开票金额
*
* @param organId
* @return
*/
BigDecimal getInvoicingAmount(Long organId);
/**
* 创建组织初始化(创建)时的购买记录
*
@@ -103,13 +85,6 @@ public interface PurchaseService {
*/
TotalSalesAmountRespVO getTotalSales();
/**
* 查询购买记录中的现金使用金额总数
*
* @return
*/
BigDecimal getTotalRechargeUsageAmount();
/**
* 查询管理端销售明细分页
*
@@ -13,11 +13,9 @@ import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.OrgEarliestPurchaseProductRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailRespVO;
@@ -30,12 +28,11 @@ import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.dal.mysql.funds.purchase.PurchaseRecordMapper;
import com.cf.imes.module.system.enums.pay.InvoiceStatusEnum;
import com.cf.imes.module.system.enums.pay.PayProductChannelCodeEnumNew;
import com.cf.imes.module.system.enums.pay.PayChannelCodeEnum;
import com.cf.imes.module.system.enums.pay.ProductDurationUnitEnum;
import com.cf.imes.module.system.enums.pay.PurchaseRecordStatusEnum;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
import com.cf.imes.module.system.framework.snowflake.config.MybatisIdProperties;
import com.cf.imes.module.system.service.funds.delay.ProductDelayService;
import com.cf.imes.module.system.service.funds.products.ProductsDetailService;
import com.cf.imes.module.system.service.organ.OrganService;
import jakarta.annotation.Resource;
@@ -80,10 +77,6 @@ public class PurchaseServiceImpl implements PurchaseService {
@Lazy
private OrganService organService;
@Resource
@Lazy
private ProductDelayService productDelayService;
@Override
public PurchaseRecordDO getRecord(Long id) {
return purchaseRecordMapper.selectById(id);
@@ -122,7 +115,7 @@ public class PurchaseServiceImpl implements PurchaseService {
List<PurchaseRecordRespVO> respVOS = new ArrayList<>();
for (PurchaseRecordDO purchaseRecordDO : resultList) {
PurchaseRecordRespVO respVO = BeanUtil.copyProperties(purchaseRecordDO, PurchaseRecordRespVO.class, "paymentMethod");
respVO.setPaymentMethod(PayProductChannelCodeEnumNew.describe(purchaseRecordDO.getPaymentMethod()));
respVO.setPaymentMethod(PayChannelCodeEnum.describe(purchaseRecordDO.getPaymentMethod()));
respVOS.add(respVO);
}
respVOS.forEach(respVO -> {
@@ -147,32 +140,6 @@ public class PurchaseServiceImpl implements PurchaseService {
.set(PurchaseRecordDO::getIsInvocing, InvoiceStatusEnum.INVOICABLE.getCode()));
}
@Override
public OrgEarliestPurchaseProductRespVO getOrgEarliestProductDetail(Long organId) {
// 查询购买记录中还有效的最晚一条
PurchaseRecordDO purchaseRecordDO = purchaseRecordMapper.selectOne(new LambdaQueryWrapper<PurchaseRecordDO>()
.eq(PurchaseRecordDO::getOrganId, organId)
.eq(PurchaseRecordDO::getDeleted, false)
.eq(PurchaseRecordDO::getStatus, PurchaseRecordStatusEnum.ACTIVE.getStatus())
.orderByDesc(PurchaseRecordDO::getCreateTime)
.last("limit 1"));
if (ObjectUtil.isNotNull(purchaseRecordDO)) {
// 查询延期记录
List<ProductDelayRespVO> recordsByPurchaseId = productDelayService.getRecordsByPurchaseId(purchaseRecordDO.getId(), organId);
if(CollUtil.isNotEmpty(recordsByPurchaseId)) {
// 延期记录是按自增id逆序的,第一条的延期后时间作为产品到期时间
purchaseRecordDO.setEndTime(recordsByPurchaseId.get(0).getDelayTime());
}
return new OrgEarliestPurchaseProductRespVO(purchaseRecordDO);
}
return null;
}
@Override
public BigDecimal getInvoicingAmount(Long organId) {
return purchaseRecordMapper.getInvoicingAmount(organId);
}
@Override
public void createOrgInitProductPurchaseRecord(Long organId, List<OrganCreateProductPurchaseReqVO> productPurchaseReqVOS) {
for (OrganCreateProductPurchaseReqVO purchaseReqVO : productPurchaseReqVOS) {
@@ -201,7 +168,6 @@ public class PurchaseServiceImpl implements PurchaseService {
.startTime(now)
// 组织创建时的套餐购买默认过期
.endTime(now.minusDays(1))
.paymentMethod(PayProductChannelCodeEnumNew.BALANCE.getCode())
.totalAmount(price)
.monthAverageAmount(monthAverageAmount)
.originalAmount(price)
@@ -296,11 +262,6 @@ public class PurchaseServiceImpl implements PurchaseService {
return purchaseRecordMapper.getTotalSales();
}
@Override
public BigDecimal getTotalRechargeUsageAmount() {
return purchaseRecordMapper.getTotalRechargeUsageAmount();
}
@Override
public PageResult<SalesDetailRespVO> getManageSalesDetailsPage(SalesDetailsPageReqVO reqVO) {
// 时间类型规范为开始0点,结束12点
@@ -318,7 +279,7 @@ public class PurchaseServiceImpl implements PurchaseService {
// 充值支付=支付宝/微信
respVO.setRechargeSpent(detailDO.getExternalSpent());
// 支付方式
respVO.setPaymentMethod(PayProductChannelCodeEnumNew.describe(detailDO.getPaymentMethod()));
respVO.setPaymentMethod(PayChannelCodeEnum.describe(detailDO.getPaymentMethod()));
// 查询组织名称
OrganizationDO organ = organService.getOrganWithDeleted(detailDO.getOrganId());
if (ObjectUtil.isNotNull(organ)) {
@@ -1,69 +0,0 @@
package com.cf.imes.module.system.service.funds.recharge;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.recharge.GiftMoneyDetailsDO;
import jakarta.validation.Valid;
import java.util.List;
/**
* 充值活动详情表 gift_money_details Service 接口
*
* @author 晨丰科技
*/
public interface RechargeActiveService {
/**
* 创建充值活动
*
* @param createReqVO
* @return 编号
*/
Long create(@Valid RechargeSaveReqVO createReqVO);
/**
* 更新充值活动
*
* @param updateReqVO 更新信息
*/
void update(@Valid RechargeSaveReqVO updateReqVO);
/**
* 删除充值活动
*
* @param id 编号
*/
void delete(Long id);
/**
* 获得充值活动,业务异常版
*
* @param id 编号
*/
GiftMoneyDetailsDO get(Long id);
/**
* 获得充值活动 分页
*
* @param pageReqVO 分页查询
*/
PageResult<GiftMoneyDetailsDO> getPage(RechargePageReqVO pageReqVO);
/**
* 获取可用充值活动
*
* @return
*/
List<GiftMoneyDetailsDO> getAvailableRechargeActiveList();
/**
* 查询充值活动,不存返回null,无业务异常
*
* @param id
* @return
*/
GiftMoneyDetailsDO getDefaultNull(Long id);
}
@@ -1,120 +0,0 @@
package com.cf.imes.module.system.service.funds.recharge;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.recharge.GiftMoneyDetailsDO;
import com.cf.imes.module.system.dal.mysql.funds.recharge.GiftMoneyDetailsMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.RECHARGE_ACTIVE_NAME_IS_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.RECHARGE_ACTIVE_NO_EXIST;
/**
* 充值活动详情表 gift_money_details Service 实现类
*
* @author 晨丰科技
*/
@Service
@Validated
public class RechargeActiveServiceImpl implements RechargeActiveService{
@Resource
private GiftMoneyDetailsMapper giftMoneyDetailsMapper;
@Override
public Long create(RechargeSaveReqVO createReqVO) {
GiftMoneyDetailsDO giftMoneyDetailsDO = giftMoneyDetailsMapper.selectOne(new LambdaQueryWrapperX<GiftMoneyDetailsDO>()
.eq(GiftMoneyDetailsDO::getDeleted, false)
.eq(GiftMoneyDetailsDO::getActivityName,createReqVO.getActivityName()));
AssertUtils.empty(giftMoneyDetailsDO,RECHARGE_ACTIVE_NAME_IS_EXIST);
GiftMoneyDetailsDO giftMoneyDetailsDOn = BeanUtils.toBean(createReqVO, GiftMoneyDetailsDO.class);
giftMoneyDetailsMapper.insert(giftMoneyDetailsDOn);
return giftMoneyDetailsDOn.getId();
}
@Override
public void update(RechargeSaveReqVO updateReqVO) {
validateRechargeActiveExists(updateReqVO.getId());
GiftMoneyDetailsDO giftMoneyDetailsDO = giftMoneyDetailsMapper.selectOne(new LambdaQueryWrapperX<GiftMoneyDetailsDO>()
.eq(GiftMoneyDetailsDO::getDeleted, false)
.eq(GiftMoneyDetailsDO::getActivityName,updateReqVO.getActivityName())
.ne(GiftMoneyDetailsDO::getId,updateReqVO.getId()));
AssertUtils.empty(giftMoneyDetailsDO,RECHARGE_ACTIVE_NAME_IS_EXIST);
GiftMoneyDetailsDO giftMoneyDetailsDOn = BeanUtils.toBean(updateReqVO, GiftMoneyDetailsDO.class);
giftMoneyDetailsMapper.updateById(giftMoneyDetailsDOn);
}
@Override
public void delete(Long id) {
validateRechargeActiveExists(id);
giftMoneyDetailsMapper.deleteById(id);
}
@Override
public GiftMoneyDetailsDO get(Long id) {
return validateRechargeActiveExists(id);
}
@Override
public GiftMoneyDetailsDO getDefaultNull(Long id) {
return giftMoneyDetailsMapper.selectById(id);
}
@Override
public PageResult<GiftMoneyDetailsDO> getPage(RechargePageReqVO pageReqVO) {
// 生成时间0点和止时间12点的区间
pageReqVO.setStartTime(LocalDateTimeUtils.generateTimeSection(pageReqVO.getStartTime()));
pageReqVO.setEndTime(LocalDateTimeUtils.generateTimeSection(pageReqVO.getEndTime()));
return giftMoneyDetailsMapper.selectPage(pageReqVO);
}
@Override
public List<GiftMoneyDetailsDO> getAvailableRechargeActiveList() {
LocalDateTime now = LocalDateTime.now();
// 筛选掉投放时间还没到和过期的
return giftMoneyDetailsMapper.selectList(new LambdaQueryWrapper<GiftMoneyDetailsDO>()
.eq(GiftMoneyDetailsDO::getDeleted, false)
.le(GiftMoneyDetailsDO::getStartTime, now)
.ge(GiftMoneyDetailsDO::getEndTime, now)
);
}
// 校验是否存在
private GiftMoneyDetailsDO validateRechargeActiveExists(Long id) {
if (id == null) {
throw exception(RECHARGE_ACTIVE_NO_EXIST);
}
GiftMoneyDetailsDO giftMoneyDetailsDO = giftMoneyDetailsMapper.selectOne(new LambdaQueryWrapperX<GiftMoneyDetailsDO>()
.eq(GiftMoneyDetailsDO::getId, id)
.eq(GiftMoneyDetailsDO::getDeleted, false));
if (giftMoneyDetailsDO == null) {
throw exception(RECHARGE_ACTIVE_NO_EXIST);
}
return giftMoneyDetailsDO;
}
}
@@ -1,19 +0,0 @@
package com.cf.imes.module.system.service.funds.recharge;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsBalanceInfoRespVO;
/**
* 充值明细 Service 接口
*
* @author Gqr
* @since 2025/9/11 16:20
*/
public interface RechargeDetailsService {
/**
* 获取管理端充值余额信息
*
* @return
*/
RechargeDetailsBalanceInfoRespVO getManageRechargeDetailsBalanceInfo();
}
@@ -1,30 +0,0 @@
package com.cf.imes.module.system.service.funds.recharge;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsBalanceInfoRespVO;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
import com.cf.imes.module.system.service.pay.PayOrderService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
/**
* 充值明细 Service 接口 实现类
*
* @author Gqr
* @since 2025/9/11 16:21
*/
@Service
public class RechargeDetailsServiceImpl implements RechargeDetailsService {
@Resource
private PayOrderService payOrderService;
@Resource
private PurchaseService purchaseService;
@Override
public RechargeDetailsBalanceInfoRespVO getManageRechargeDetailsBalanceInfo() {
RechargeDetailsBalanceInfoRespVO rechargeDetailsBalanceInfoRespVO = new RechargeDetailsBalanceInfoRespVO();
rechargeDetailsBalanceInfoRespVO.setRechargeAmount(payOrderService.getRechargeTotalAmount());
rechargeDetailsBalanceInfoRespVO.setRechargeUsageAmount(purchaseService.getTotalRechargeUsageAmount());
return rechargeDetailsBalanceInfoRespVO;
}
}
@@ -2,7 +2,6 @@ package com.cf.imes.module.system.service.pay;
import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayProductOrderUnifiedReqVO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayRechargeOrderReqVO;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderDO;
import java.math.BigDecimal;
@@ -38,13 +37,6 @@ public interface PayOrderService {
*/
String getProductPayExpireTime(PayProductOrderUnifiedReqVO payProductOrderUnifiedReqVO);
/**
* 账户充值支付
*
* @param payRechargeOrderReqVO
*/
PayOrderRespDTO rechargePay(PayRechargeOrderReqVO payRechargeOrderReqVO);
/**
* 查询支付订单支付状态
* 未支付、超时等都抛出支付异常
@@ -3,7 +3,6 @@ package com.cf.imes.module.system.service.pay;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -11,7 +10,6 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.common.util.validation.ValidationUtils;
import com.cf.imes.framework.id.core.util.SnowflakeSerialNoWorker3rd;
@@ -26,32 +24,24 @@ import com.cf.imes.module.system.controller.admin.pay.vo.PayOrderUnifiedReqDTO;
import com.cf.imes.framework.common.exception.PayException;
import com.cf.imes.framework.pay.core.enums.order.PayOrderStatusRespEnum;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganRechargeAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductProcessorRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.delay.ProductDelayRecordDO;
import com.cf.imes.module.system.enums.pay.PayProductChannelCodeEnumNew;
import com.cf.imes.module.system.dal.dataobject.funds.productpromotion.ProductPromotionDO;
import com.cf.imes.module.system.enums.pay.ProductDurationUnitEnum;
import com.cf.imes.module.system.service.funds.delay.ProductDelayService;
import com.cf.imes.module.system.service.funds.productpromotion.ProductPromotionService;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
import com.cf.imes.module.system.controller.admin.pay.vo.PayProductOrderUnifiedReqVO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayRechargeOrderReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.organamount.OrganAmountDO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import com.cf.imes.module.system.dal.dataobject.funds.recharge.GiftMoneyDetailsDO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
import com.cf.imes.module.system.enums.pay.IncomeExpenseTypeEnum;
import com.cf.imes.module.system.enums.pay.PayChannelCodeEnum;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
import com.cf.imes.module.system.enums.recharge.RechargeGiftTypeEnum;
import com.cf.imes.module.system.enums.recharge.RechargeTypeEnum;
import com.cf.imes.module.system.framework.snowflake.config.MybatisIdProperties;
import com.cf.imes.module.system.service.funds.incomeandexpense.IncomeExpenseService;
import com.cf.imes.module.system.service.funds.organamount.OrganAmountService;
import com.cf.imes.module.system.service.funds.products.ProductsDetailService;
import com.cf.imes.module.system.service.funds.recharge.RechargeActiveService;
import com.cf.imes.module.system.service.organ.OrganService;
import com.cf.imes.module.system.service.pay.factory.impl.AbstractPayHandler;
import com.cf.imes.module.system.service.pay.factory.PayHandlerFactory;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderDO;
@@ -67,7 +57,6 @@ import jakarta.annotation.Resource;
import jakarta.validation.Validator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
@@ -78,16 +67,12 @@ import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.e
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORG_PRODUCT_PURCHASE_LOCK_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORG_PRODUCT_PURCHASE_WAIT_PAY_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_CHANNEL_NOT_SUPPORT;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_NOTIFY_PASSBACK_TRADETYPE_NOT_SUPPORT_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_CHANNEL_QUERY_NOT_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_NOTIFY_DATA_PARSE_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_NOT_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_SUBMIT_CHANNEL_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_RECHARGE_ACTIVITY_CHANNEL_MISMATCH_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_RECHARGE_ACTIVITY_EXPIRE_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_RECHARGE_ORDER_ORGANID_CHECK_ERROR;
/**
* 支付订单接口 实现类
@@ -122,9 +107,6 @@ public class PayOrderServiceImpl implements PayOrderService {
@Resource
private ProductsDetailService productsDetailService;
@Resource
private OrganAmountService organAmountService;
@Resource
private IncomeExpenseService incomeExpenseService;
@@ -134,12 +116,6 @@ public class PayOrderServiceImpl implements PayOrderService {
@Resource
private MybatisIdProperties mybatisIdProperties;
@Resource
private RechargeActiveService rechargeActiveService;
@Resource
private OrganService organService;
@Resource
private ProductDelayService productDelayService;
@@ -155,6 +131,9 @@ public class PayOrderServiceImpl implements PayOrderService {
@Resource
private SnowflakeSerialNoWorker3rd snowflakeSerialNoWorker3rd;
@Resource
private ProductPromotionService productPromotionService;
@Override
public PayOrderDO get(Long id) {
return payOrderMapper.selectById(id);
@@ -169,10 +148,6 @@ public class PayOrderServiceImpl implements PayOrderService {
// 主动校验一次入参
ValidationUtils.validate(validator, payProductOrderUnifiedReqVO);
// 校验组合渠道
List<PayProductChannelCodeEnumNew> parse = PayProductChannelCodeEnumNew.parse(payProductOrderUnifiedReqVO.getProductChannelCode());
AssertUtils.notEmpty(parse, PAY_CHANNEL_NOT_SUPPORT);
// 校验产品和产品明细
Long productId = payProductOrderUnifiedReqVO.getProductId();
ProductsDO productsDO = productsDetailService.validateProductExist(productId);
@@ -189,7 +164,7 @@ public class PayOrderServiceImpl implements PayOrderService {
PayOrderUnifiedReqDTO payOrderUnifiedReqDTO = null;
// 获取渠道方处理器
Integer channelCode = PayProductChannelCodeEnumNew.hasAlipay(payProductOrderUnifiedReqVO.getProductChannelCode()) ? PayChannelCodeEnum.ALIPAY_PC.getCode() : PayChannelCodeEnum.WECHAT_NATIVE.getCode();
Integer channelCode = payProductOrderUnifiedReqVO.getProductChannelCode();
try {
// 检查机构产品是否有待支付的购买记录
List<PurchaseRecordDO> pendingPurchaseList = purchaseService.getOrgProductPendingPurchaseList(organId, productId);
@@ -197,17 +172,17 @@ public class PayOrderServiceImpl implements PayOrderService {
throw new ServiceException(ORG_PRODUCT_PURCHASE_WAIT_PAY_ERROR);
}
// 查询组织余额信息
OrganAmountDO organAmount = organAmountService.validOrganAmount(organId);
// 查询组织产品的首次购买记录
PurchaseRecordDO orgInitialPurchaseRecord = purchaseService.getOrgInitialPurchaseRecord(organId, productsDO.getId());
// 查询组织有效产品购买记录下的延期记录
PreviouProductDelayRespVO previouProductDelayRespVO = productDelayService.getActiveRecordsByProductId(productId, organId);
// 查询可用的优惠活动
List<ProductPromotionDO> availableProductPromotionList = productPromotionService.getAvailableProductPromotionList(productId);
// 根据购买类型做价格处理
PayProductProcessorNew payProductProcessorNew = new PayProductProcessorNew(productsDO, productsDetailDO, orgInitialPurchaseRecord, previouProductDelayRespVO, organAmount, organId, payConfig, mybatisIdProperties, snowflakeSerialNoWorker3rd);
PayProductProcessorNew payProductProcessorNew = new PayProductProcessorNew(productsDO, productsDetailDO, orgInitialPurchaseRecord, previouProductDelayRespVO, availableProductPromotionList, organId, payConfig, mybatisIdProperties);
ProductProcessorRespVO productProcessorRespVO = payProductProcessorNew.processPayment(payProductOrderUnifiedReqVO.getProductChannelCode());
PayOrderDO payOrder = productProcessorRespVO.getPayOrderDO();
@@ -218,29 +193,14 @@ public class PayOrderServiceImpl implements PayOrderService {
// 记录入库,如果有外部支付发起请求二维码
// 购买记录入库
purchaseService.createRecord(productProcessorRespVO.getPurchaseRecordDO());
// 收支明细入库
IncomeExpenseDetailsDO incomeExpenseDetailsDO = productProcessorRespVO.getIncomeExpenseDetailsDO();
if (ObjectUtil.isNotNull(incomeExpenseDetailsDO)) {
incomeExpenseService.createDetail(incomeExpenseDetailsDO);
}
// 更新组织资金,纯第三方支付不需要更新余额
OrganAmountDO finalOrganAmountDO = productProcessorRespVO.getOrganAmountDO();
if (ObjectUtil.isNotNull(finalOrganAmountDO)) {
organAmountService.productPay(finalOrganAmountDO);
}
// 发起渠道方支付
createPayOrder(payOrder);
AbstractPayHandler payHandler = payHandlerFactory.getPayHandler(channelCode);
// 如果有外部支付,发起请求
if (ObjectUtil.isNotNull(payOrder)) {
createPayOrder(payOrder);
payOrderUnifiedReqDTO = createPayOrderUnifiedReqDTO(payOrder);
return payHandler.unifiedOrder(payOrderUnifiedReqDTO);
// 发起渠道方支付
AbstractPayHandler payHandler = payHandlerFactory.getPayHandler(channelCode);
payOrderUnifiedReqDTO = createPayOrderUnifiedReqDTO(payOrder);
return payHandler.unifiedOrder(payOrderUnifiedReqDTO);
}
return null;
} catch (Throwable e) {
// 系统异常,则包装成 PayException 异常抛出
log.error("[unifiedOrder][客户端({}) request({}) 发起支付异常]",
@@ -283,8 +243,11 @@ public class PayOrderServiceImpl implements PayOrderService {
// 查询组织有效产品购买记录下的延期记录
PreviouProductDelayRespVO previouProductDelayRespVO = productDelayService.getActiveRecordsByProductId(productId, organId);
// 查询可用的优惠活动
List<ProductPromotionDO> availableProductPromotionList = productPromotionService.getAvailableProductPromotionList(productId);
// 根据购买类型做价格处理
PayProductProcessorNew payProductProcessor = new PayProductProcessorNew(productsDO, productsDetailDO, orgInitialPurchaseRecord, previouProductDelayRespVO, null, organId, null, null, null);
PayProductProcessorNew payProductProcessor = new PayProductProcessorNew(productsDO, productsDetailDO, orgInitialPurchaseRecord, previouProductDelayRespVO, availableProductPromotionList, organId, null, null);
return LocalDateTimeUtil.format(payProductProcessor.getProductPayExpireTime(), FORMAT_YEAR_MONTH_DAY);
}
@@ -353,136 +316,6 @@ public class PayOrderServiceImpl implements PayOrderService {
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public PayOrderRespDTO rechargePay(PayRechargeOrderReqVO payRechargeOrderReqVO) {
// 主动校验一次入参
ValidationUtils.validate(validator, payRechargeOrderReqVO);
Long organId = payRechargeOrderReqVO.getOrganId();
// 校验组织名称
AssertUtils.notEquals(organId, SecurityFrameworkUtils.getUserOrganId(), PAY_RECHARGE_ORDER_ORGANID_CHECK_ERROR);
// 校验组织套餐
organAmountService.validOrganAmount(organId);
// 获取渠道方处理器
Integer channelCode = payRechargeOrderReqVO.getChannelCode();
AbstractPayHandler payHandler = payHandlerFactory.getPayHandler(channelCode);
// 创建支付订单
PayOrderDO payOrder = createRechargePayOrder(payRechargeOrderReqVO.getPrice(), "imes充值", channelCode);
// 设置赠送活动编号
Long rechargeActivityId = payRechargeOrderReqVO.getRechargeActivityId();
if (ObjectUtil.isNotNull(rechargeActivityId)) {
// 校验活动类型和渠道是否匹配
validRechargeActivity(rechargeActivityId, channelCode);
payOrder.setRechargeActivityId(rechargeActivityId);
}
createPayOrder(payOrder);
// 发起渠道方支付
PayOrderUnifiedReqDTO payOrderUnifiedReqDTO = null;
try {
payOrderUnifiedReqDTO = createPayOrderUnifiedReqDTO(payOrder);
return payHandler.unifiedOrder(payOrderUnifiedReqDTO);
} catch (Throwable e) {
// 系统异常,则包装成 PayException 异常抛出
log.error("[unifiedOrder][客户端({}) request({}) 发起支付异常]",
channelCode, JSON.toJSONString(payOrderUnifiedReqDTO), e);
throw new PayException(PAY_ORDER_SUBMIT_CHANNEL_ERROR);
}
}
/**
* 校验充值活动和渠道是否匹配
*
* @param rechargeActivityId 活动id
* @param channelCode 支付渠道编码
*/
private void validRechargeActivity(Long rechargeActivityId, Integer channelCode) {
GiftMoneyDetailsDO giftMoneyDetailsDO = rechargeActiveService.get(rechargeActivityId);
Integer rechargeType = giftMoneyDetailsDO.getRechargeType();
// 当充值活动只支持微信时,渠道只能是微信
if (RechargeTypeEnum.isWechat(rechargeType) && !PayChannelCodeEnum.isWechat(channelCode)) {
throw ServiceExceptionUtil.exception(PAY_RECHARGE_ACTIVITY_CHANNEL_MISMATCH_ERROR);
}
// 当充值活动只支持支付宝,渠道只能是支付宝
if (RechargeTypeEnum.isAlipay(rechargeType) && !PayChannelCodeEnum.isAlipay(channelCode)) {
throw ServiceExceptionUtil.exception(PAY_RECHARGE_ACTIVITY_CHANNEL_MISMATCH_ERROR);
}
// 校验是否过期
if (giftMoneyDetailsDO.getEndTime().isBefore(LocalDateTime.now())) {
throw new ServiceException(PAY_RECHARGE_ACTIVITY_EXPIRE_ERROR);
}
}
/**
* 计算赠送金
*
* @param rechargeActivityId
* @param rechargeAmount
* @return
*/
private BigDecimal calcGiftAmount(Long rechargeActivityId, BigDecimal rechargeAmount) {
BigDecimal totalGift = null;
if (ObjectUtil.isNull(rechargeActivityId)) {
return totalGift;
}
GiftMoneyDetailsDO rechargeActivityDO = rechargeActiveService.getDefaultNull(rechargeActivityId);
if (ObjectUtil.isNotNull(rechargeActivityDO)) {
// 赠送活动已经过期
if (rechargeActivityDO.getEndTime().isBefore(LocalDateTime.now())) {
return totalGift;
}
} else {
return totalGift;
}
BigDecimal threshold = rechargeActivityDO.getRechargeAmount();
BigDecimal giftAmount = rechargeActivityDO.getGiftAmount();
switch (RechargeGiftTypeEnum.fromStatus(rechargeActivityDO.getRechargeGiftType())) {
case FULL_X_GIVE_X:
// 满 threshold 才送 giftAmount
if (rechargeAmount.compareTo(threshold) >= 0) {
totalGift = giftAmount;
}
break;
case EVERY_X_GIVE_X:
// 每满 threshold 送 giftAmount,可累计
BigDecimal times = rechargeAmount.divide(threshold, 0, RoundingMode.FLOOR);
totalGift = times.multiply(giftAmount);
break;
}
return totalGift;
}
/**
* 创建充值支付订单
*
* @param
* @return
*/
private PayOrderDO createRechargePayOrder(BigDecimal price, String subject, Integer channelCode) {
PayOrderDO payOrderDO = new PayOrderDO();
Long payOrderId = IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId();
Long organId = SecurityFrameworkUtils.getUserOrganId();
payOrderDO.setId(payOrderId);
payOrderDO.setStatus(PayOrderStatusEnum.WAITING);
payOrderDO.setExpireTime(LocalDateTime.now().plus(payConfig.getPayExpireTime()));
payOrderDO.setPrice(price);
payOrderDO.setSubject(subject);
payOrderDO.setChannelCode(PayChannelCodeEnum.fromType(channelCode));
payOrderDO.setOrganId(organId);
payOrderDO.setTradeType(TradeTypeEnum.RECHARGE.getCode());
return payOrderDO;
}
/**
* 创建支付渠道方请求对象
*
@@ -610,9 +443,6 @@ public class PayOrderServiceImpl implements PayOrderService {
// 3. 根据交易类型做对应回调处理
switch (TradeTypeEnum.fromCode(order.getTradeType())) {
case RECHARGE:
notifyRechargeOrderSuccess(order, organId);
break;
case PRODUCT:
notifyProductPayOrderSuccess(order);
break;
@@ -621,43 +451,6 @@ public class PayOrderServiceImpl implements PayOrderService {
}
}
/**
* 充值成功回调
*
* @param payOrderDO
* @param organId
*/
private void notifyRechargeOrderSuccess(PayOrderDO payOrderDO, Long organId) {
// 支付订单的金额
BigDecimal price = payOrderDO.getPrice();
// 订单流水号
Long payOrderId = payOrderDO.getId();
// 1.更新组织资金
// 检查赠送金是否存在已经是否在有效期,有效的话计入组织充值赠送金
BigDecimal giftAmount = calcGiftAmount(payOrderDO.getRechargeActivityId(), price);
// 更新
OrganRechargeAmountRespVO rechargeAmountRespVO = organAmountService.recharge(organId, price, giftAmount);
// 2.新增收支明细
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.orderNo(String.valueOf(payOrderId))
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.tradeType(TradeTypeEnum.RECHARGE.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.INCOME.getCode())
.cashAmountChange(price)
.giftAmountChange(giftAmount)
.availableAmount(rechargeAmountRespVO.getAvailableAmount())
.amount(rechargeAmountRespVO.getAmount())
.giftAmount(rechargeAmountRespVO.getGiftAmount())
.build();
incomeExpenseDetailsDO.setCreator(payOrderDO.getCreator());
incomeExpenseDetailsDO.setUpdater(payOrderDO.getUpdater());
incomeExpenseService.createDetail(incomeExpenseDetailsDO);
}
/**
* 产品购买成功回调
*
@@ -686,22 +479,19 @@ public class PayOrderServiceImpl implements PayOrderService {
// 4、激活本次的购买记录
purchaseService.activateHistoryOrganProductPurchaseRecord(organId, purchaseId);
// 5.如果是纯第三方支付需要新增收支明细
Integer paymentMethod = record.getPaymentMethod();
if (PayProductChannelCodeEnumNew.hasAlipay(paymentMethod) || PayProductChannelCodeEnumNew.hasWechat(paymentMethod)) {
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.orderNo(String.valueOf(payOrderDO.getId()))
.purchaseId(purchaseId)
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
.cashAmountChange(price)
.build();
incomeExpenseDetailsDO.setCreator(payOrderDO.getCreator());
incomeExpenseDetailsDO.setUpdater(payOrderDO.getUpdater());
incomeExpenseService.createDetail(incomeExpenseDetailsDO);
}
// 5.新增收支明细
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.orderNo(String.valueOf(payOrderDO.getId()))
.purchaseId(purchaseId)
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
.amount(price)
.build();
incomeExpenseDetailsDO.setCreator(payOrderDO.getCreator());
incomeExpenseDetailsDO.setUpdater(payOrderDO.getUpdater());
incomeExpenseService.createDetail(incomeExpenseDetailsDO);
}
}
@@ -752,9 +542,6 @@ public class PayOrderServiceImpl implements PayOrderService {
// 3. 根据交易类型做对应回调处理
switch (TradeTypeEnum.fromCode(order.getTradeType())) {
case RECHARGE:
notifyRechargeOrderFail(order, organId);
break;
case PRODUCT:
notifyProductPayOrderFail(order);
break;
@@ -763,16 +550,6 @@ public class PayOrderServiceImpl implements PayOrderService {
}
}
/**
* 充值失败回调
*
* @param payOrderDO
* @param organId
*/
private void notifyRechargeOrderFail(PayOrderDO payOrderDO, Long organId) {
// todo 充值失败回调
}
/**
* 产品购买失败回调
*
@@ -786,33 +563,7 @@ public class PayOrderServiceImpl implements PayOrderService {
// 1、产品购买第三方支付失败 删除购买记录
purchaseService.deleteRecord(purchaseId);
BigDecimal zero = BigDecimal.ZERO;
BigDecimal accountBalanceSpent = record.getAccountBalanceSpent();
BigDecimal giftMoneySpent = record.getGiftMoneySpent();
// 如果现金花费和赠送金花费任一不为0,则代表有要退回的操作
if (accountBalanceSpent.compareTo(zero) > 0 || giftMoneySpent.compareTo(zero) > 0) {
// 2、混合支付失败,退回扣除的现金和赠送金
OrganRechargeAmountRespVO organRefundProductRespVO = organAmountService.refundProductOrganAmountBalanceAndGift(organId, accountBalanceSpent, giftMoneySpent);
// 3、新增退回的收支记录
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.purchaseId(purchaseId)
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.INCOME.getCode())
.cashAmountChange(accountBalanceSpent)
.giftAmountChange(giftMoneySpent)
.availableAmount(organRefundProductRespVO.getAvailableAmount())
.amount(organRefundProductRespVO.getAmount())
.giftAmount(organRefundProductRespVO.getGiftAmount())
.build();
incomeExpenseDetailsDO.setCreator(record.getCreator());
incomeExpenseDetailsDO.setUpdater(record.getUpdater());
incomeExpenseService.createDetail(incomeExpenseDetailsDO);
}
// 4、重置前序产品购买记录下延期记录的备注
// 2、重置前序产品购买记录下延期记录的备注
Long previousId = record.getPreviousId();
if (ObjectUtil.isNotNull(previousId)) {
productDelayService.resetPurchaseDelayRecordsRemark(previousId, organId);
@@ -7,22 +7,19 @@ import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.id.core.util.SnowflakeSerialNoWorker3rd;
import com.cf.imes.framework.pay.config.ChenfengPayConfig;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.PreviouProductDelayRespVO;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO;
import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductProcessorRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.organamount.OrganAmountDO;
import com.cf.imes.module.system.dal.dataobject.funds.productpromotion.ProductPromotionDO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderDO;
import com.cf.imes.module.system.enums.pay.IncomeExpenseTypeEnum;
import com.cf.imes.module.system.enums.pay.DurationUnitEnum;
import com.cf.imes.module.system.enums.pay.InvoiceStatusEnum;
import com.cf.imes.module.system.enums.pay.PayChannelCodeEnum;
import com.cf.imes.module.system.enums.pay.PayOrderStatusEnum;
import com.cf.imes.module.system.enums.pay.PayProductChannelCodeEnumNew;
import com.cf.imes.module.system.enums.pay.ProductDurationUnitEnum;
import com.cf.imes.module.system.enums.pay.PurchaseRecordStatusEnum;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
@@ -37,9 +34,8 @@ import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_PRODUCT_BALANCE_INSUFFICIENT;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_PRODUCT_GIFT_BALANCE_INSUFFICIENT;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCT_PURCHASE_ENDTIME_BEFORE_DELAYTIME_ERROR;
@@ -60,9 +56,6 @@ public class PayProductProcessorNew {
// 组织产品的首次订购记录
private PurchaseRecordDO orgInitialPurchaseRecord;
// 当前组织资金信息
private OrganAmountDO organAmountDO;
// 组织id
private Long organId;
@@ -72,9 +65,6 @@ public class PayProductProcessorNew {
// id生成规则配置
private MybatisIdProperties mybatisIdProperties;
// id生成器
private SnowflakeSerialNoWorker3rd snowflakeSerialNoWorker3rd;
// 标记本次订购是否首次
private boolean initialized = false;
@@ -105,41 +95,27 @@ public class PayProductProcessorNew {
// 按序流转价格
private BigDecimal price;
// 组织赠送金
private BigDecimal gift;
// 组织现金
private BigDecimal balance;
// 使用赠送金
private BigDecimal usedGift;
// 使用余额
private BigDecimal usedBalance;
// 支付类型
private Integer payType;
// 当次购买记录DO
private PurchaseRecordDO purchaseRecordDO;
// 当次收支记录DO
private IncomeExpenseDetailsDO incomeExpenseDetailsDO;
// 当次支付订单DO
private PayOrderDO payOrderDO;
// 是否只用了赠送金
private boolean justPayGift = false;
// 优惠活动id
private Long productPromotionId;
// 最终存储的支付方式,通过实际支付做二进制部位,例如有可能选择了现金+赠送金但是只用了赠送金,就只补赠送金位
private int payMethod;
// 可用的产品优惠活动列表
private List<ProductPromotionDO> availableProductPromotionList;
public PayProductProcessorNew(ProductsDO productsDO, ProductsDetailDO productsDetailDO, PurchaseRecordDO orgInitialPurchaseRecord, PreviouProductDelayRespVO previouProductDelayRespVO,
OrganAmountDO organAmountDO, Long organId, ChenfengPayConfig payConfig, MybatisIdProperties mybatisIdProperties, SnowflakeSerialNoWorker3rd snowflakeSerialNoWorker3rd) {
List<ProductPromotionDO> availableProductPromotionList, Long organId, ChenfengPayConfig payConfig, MybatisIdProperties mybatisIdPropertiesd) {
this.productsDO = productsDO;
this.productsDetailDO = productsDetailDO;
this.orgInitialPurchaseRecord = orgInitialPurchaseRecord;
this.availableProductPromotionList = availableProductPromotionList;
if (ObjectUtil.isNotNull(previouProductDelayRespVO.getPreviouPurchaseRecord())) {
delayRespVOList = previouProductDelayRespVO.getDelayRespVOList();
previousPurchaseRecord = previouProductDelayRespVO.getPreviouPurchaseRecord();
@@ -151,11 +127,9 @@ public class PayProductProcessorNew {
// 首次订购正常从今天开始累加算世界时间
endTime = addTime(startTime, productsDetailDO.getDuration(), productsDetailDO.getDurationUnit());
}
this.organAmountDO = organAmountDO;
this.organId = organId;
this.payConfig = payConfig;
this.mybatisIdProperties = mybatisIdProperties;
this.snowflakeSerialNoWorker3rd = snowflakeSerialNoWorker3rd;
}
/**
@@ -175,105 +149,21 @@ public class PayProductProcessorNew {
// 首次购买记录是空,那么当前就是首次订购
initialized = true;
}
// 当前组织的余额
balance = organAmountDO.getAmount();
// 当前组织的赠送金
gift = organAmountDO.getGiftAmount();
this.payType = payType;
// 按序扣款
deduction();
// 三方支付
payByExternal();
// 根据扣款情况生成购买记录和收支记录
generatePurchaseRecordAndIncomeRecord();
return new ProductProcessorRespVO(purchaseRecordDO, incomeExpenseDetailsDO, payOrderDO, organAmountDO, delayRespVOList);
}
/**
* 按顺序扣款
*/
private void deduction(){
// 有赠送金先扣赠送金
if (PayProductChannelCodeEnumNew.hasGift(payType)) {
payByGift();
if (price.compareTo(BigDecimal.ZERO) == 0) {
// 赠送金直接扣完了,开出的购买记录为不可开票
justPayGift = true;
return;
}
}
// 有现金扣现金
if(PayProductChannelCodeEnumNew.hasBalance(payType)) {
payByBalance();
if (price.compareTo(BigDecimal.ZERO) == 0) {
return;
}
}
// 有第三方支付走第三方
if (PayProductChannelCodeEnumNew.hasAlipay(payType) || PayProductChannelCodeEnumNew.hasWechat(payType)) {
payByExternal();
}
}
/**
* 赠送金支付
*/
private void payByGift() {
// 赠送金余额减去购买金额
usedGift = price.min(gift);
price = price.subtract(usedGift);
// 更新余额
organAmountDO.setAmount(organAmountDO.getAmount());
organAmountDO.setGiftAmount(gift.subtract(usedGift));
// 有效扣除累加payMethod
if (usedGift.compareTo(BigDecimal.ZERO) > 0) {
payMethod |= PayProductChannelCodeEnumNew.GIFT.getCode();
}
}
/**
* 余额支付
*/
private void payByBalance() {
//现金余额减去购买金额
usedBalance = price.min(balance);
price = price.subtract(usedBalance);
// 更新余额
organAmountDO.setAmount(balance.subtract(usedBalance));
organAmountDO.setGiftAmount(organAmountDO.getGiftAmount());
// 有效扣除累加payMethod
if (usedBalance.compareTo(BigDecimal.ZERO) > 0) {
payMethod |= PayProductChannelCodeEnumNew.BALANCE.getCode();
}
return new ProductProcessorRespVO(purchaseRecordDO, payOrderDO, delayRespVOList);
}
/**
* 根据扣款情况生成购买记录和收支记录
*/
private void generatePurchaseRecordAndIncomeRecord() {
// 扣款价格大于0
if (price.compareTo(BigDecimal.ZERO) > 0) {
// 只有赠送金
if (PayProductChannelCodeEnumNew.isGiftOnly(payType)) {
throw new ServiceException(PAY_PRODUCT_GIFT_BALANCE_INSUFFICIENT);
}
// 只有现金/现金+赠送金
if (PayProductChannelCodeEnumNew.isBalanceOnly(payType) || PayProductChannelCodeEnumNew.isBalanceAndGift(payType)) {
throw new ServiceException(PAY_PRODUCT_BALANCE_INSUFFICIENT);
}
}
// 扣款完成,生成记录
// 新增购买记录
long purchaseId = IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId();
purchaseRecordDO = PurchaseRecordDO.builder()
@@ -286,59 +176,26 @@ public class PayProductProcessorNew {
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.startTime(startTime)
.endTime(endTime)
.paymentMethod(payMethod)
.paymentMethod(payType)
.totalAmount(productPrice)
.originalAmount(originalPrice)
.monthAverageAmount(monthAverageAmount)
.accountBalanceSpent(usedBalance)
.giftMoneySpent(usedGift)
.isInvocing(justPayGift ? null : InvoiceStatusEnum.INVOICABLE.getCode())
.isInvocing(InvoiceStatusEnum.INVOICABLE.getCode())
.initial(initialized)
.status(PurchaseRecordStatusEnum.ACTIVE.getStatus())
.previousId(previousPurchaseRecordId)
.productPromotionId(productPromotionId)
.build();
// 以上检查都通过,走的是第三方支付
if(ObjectUtil.isNotNull(payOrderDO)) {
// 第三方支付在异步回调后创建收支记录
// 第三方支付在异步回调后创建收支记录
payOrderDO.setPurchaseId(purchaseId);
payOrderDO.setPurchaseId(purchaseId);
if (PayProductChannelCodeEnumNew.hasAlipay(payType)) {
payOrderDO.setChannelCode(PayChannelCodeEnum.ALIPAY_PC);
// 有效扣除累加payMethod
payMethod |= PayProductChannelCodeEnumNew.ALIPAY.getCode();
purchaseRecordDO.setPaymentMethod(payMethod);
} else if (PayProductChannelCodeEnumNew.hasWechat(payType)) {
payOrderDO.setChannelCode(PayChannelCodeEnum.WECHAT_NATIVE);
// 有效扣除累加payMethod
payMethod |= PayProductChannelCodeEnumNew.WECHAT.getCode();
purchaseRecordDO.setPaymentMethod(payMethod);
}
// 记录第三方支付金额
purchaseRecordDO.setExternalSpent(price);
// 购买记录为等待支付
purchaseRecordDO.setStatus(PurchaseRecordStatusEnum.PENDING.getStatus());
// 更新为不可开票,等异步回调后修改为可开票
purchaseRecordDO.setIsInvocing(null);
} else {
BigDecimal amount = organAmountDO.getAmount();
BigDecimal giftAmount = organAmountDO.getGiftAmount();
incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.purchaseId(purchaseRecordDO.getId())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
.cashAmountChange(usedBalance)
.giftAmountChange(usedGift)
.availableAmount(amount.add(giftAmount))
.amount(amount)
.giftAmount(giftAmount)
.build();
}
// 记录第三方支付金额
purchaseRecordDO.setExternalSpent(price);
// 购买记录为等待支付
purchaseRecordDO.setStatus(PurchaseRecordStatusEnum.PENDING.getStatus());
// 更新为不可开票,等异步回调后修改为可开票
purchaseRecordDO.setIsInvocing(null);
}
@@ -357,6 +214,12 @@ public class PayProductProcessorNew {
payOrderDO.setSubject(productsDO.getProductName());
payOrderDO.setOrganId(organId);
payOrderDO.setTradeType(TradeTypeEnum.PRODUCT.getCode());
purchaseRecordDO.setPaymentMethod(payType);
if (PayChannelCodeEnum.isAlipay(payType)) {
payOrderDO.setChannelCode(PayChannelCodeEnum.ALIPAY_PC);
} else if (PayChannelCodeEnum.isWechat(payType)) {
payOrderDO.setChannelCode(PayChannelCodeEnum.WECHAT_NATIVE);
}
}
/**
@@ -412,6 +275,11 @@ public class PayProductProcessorNew {
endTime = endTime.minusDays(delayDays);
}
// 5、累加优惠活动的赠送时间
if (CollUtil.isNotEmpty(availableProductPromotionList)) {
calculateGiftDuration(duration, durationUnit);
}
if (endTime.isBefore(today)) {
throw ServiceExceptionUtil.exception(PRODUCT_PURCHASE_ENDTIME_BEFORE_DELAYTIME_ERROR, LocalDateTimeUtil.format(endTime, DatePattern.NORM_DATE_PATTERN));
}
@@ -419,6 +287,32 @@ public class PayProductProcessorNew {
return endTime;
}
/**
*
* @param duration
* @param durationUnit
*/
private void calculateGiftDuration(Integer duration, Integer durationUnit) {
Optional<ProductPromotionDO> availableProductPromotionOpt = availableProductPromotionList.stream()
.filter(p -> duration.equals(p.getPurchaseDuration()) && durationUnit.equals(p.getPurchaseDurationUnit()))
.findFirst();
if (availableProductPromotionOpt.isEmpty()) {
// 没有精确匹配时,找同单位中 purchaseDuration 与 duration 差值最小的
availableProductPromotionOpt = availableProductPromotionList.stream()
.filter(p -> durationUnit.equals(p.getPurchaseDurationUnit()))
.min(Comparator.comparing(p -> BigDecimal.valueOf(
Math.abs(p.getPurchaseDuration() - duration))
));
}
if (availableProductPromotionOpt.isPresent()) {
ProductPromotionDO productPromotionDO = availableProductPromotionOpt.get();
productPromotionId = productPromotionDO.getId();
endTime = addTime(endTime, productPromotionDO.getGiftDuration(), productPromotionDO.getGiftDurationUnit());
}
}
/**
* 计算总延期天数(合并区间,避免重叠/不连续)
*/
@@ -517,11 +411,13 @@ public class PayProductProcessorNew {
* @return
*/
private static LocalDate addTime(LocalDate time, int duration, int unit) {
switch (ProductDurationUnitEnum.fromStatus(unit)) {
switch (DurationUnitEnum.fromStatus(unit)) {
case YEAR:
return time.plusYears(duration);
case MONTH:
return time.plusMonths(duration);
case DAY:
return time.plusDays(duration);
default:
return time;
}
@@ -1,32 +0,0 @@
package com.cf.imes.module.system.validation.manualadjust;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 手工调账类型校验注解
*
* @author Gqr
* @since 2025/9/16 10:45
*/
@Target({
ElementType.FIELD,
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {AdjustTypeValidator.class}
)
public @interface AdjustTypeValid {
String message() default "调账类型不合法";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -1,34 +0,0 @@
package com.cf.imes.module.system.validation.manualadjust;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.module.system.enums.pay.AdjustTypeEnum;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.Objects;
/**
* 手工调账类型校验器
*
* @author Gqr
* @since 2025/9/16 10:46
*/
public class AdjustTypeValidator implements ConstraintValidator<AdjustTypeValid, Integer> {
@Override
public void initialize(AdjustTypeValid constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
if (ObjectUtil.isNull(value)) {
return true;
}
for (AdjustTypeEnum type : AdjustTypeEnum.values()) {
if (Objects.equals(type.getType(), value)) {
return true;
}
}
return false;
}
}
@@ -1,26 +0,0 @@
package com.cf.imes.module.system.validation.recharge;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
/**
* 赠送类型校验注解
*/
@Target({
ElementType.FIELD,
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {RechargeGiftTypeValidator.class}
)
public @interface RechargeGiftTypeValid {
String message() default "赠送类型不合法,0:满X送X; 1:每满X送X";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -1,27 +0,0 @@
package com.cf.imes.module.system.validation.recharge;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.module.system.enums.recharge.RechargeGiftTypeEnum;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.Objects;
/**
* 赠送类型校验器
*/
public class RechargeGiftTypeValidator implements ConstraintValidator<RechargeGiftTypeValid, Integer> {
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (ObjectUtil.isNull(value)) {
return true;
}
for (RechargeGiftTypeEnum statusEnum : RechargeGiftTypeEnum.values()) {
if (Objects.equals(statusEnum.getStatus(), value)) {
return true;
}
}
return false;
}
}
@@ -1,26 +0,0 @@
package com.cf.imes.module.system.validation.recharge;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
/**
* 充值类型校验注解
*/
@Target({
ElementType.FIELD,
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {RechargeTypeValidator.class}
)
public @interface RechargeType {
String message() default "充值类型不合法, 0:微信、支付宝 1:微信 2:支付宝";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -1,26 +0,0 @@
package com.cf.imes.module.system.validation.recharge;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.module.system.enums.recharge.RechargeTypeEnum;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.Objects;
/**
* 充值类型校验器
*/
public class RechargeTypeValidator implements ConstraintValidator<RechargeType, Integer> {
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (ObjectUtil.isNull(value)) {
return true;
}
for (RechargeTypeEnum statusEnum : RechargeTypeEnum.values()) {
if (Objects.equals(statusEnum.getStatus(), value)) {
return true;
}
}
return false;
}
}
@@ -29,19 +29,4 @@
GROUP BY date
</select>
<select id="getTotalRechargeAmount" resultType="java.math.BigDecimal">
select sum(amount) as amount
from system_organization_amount
where deleted = false
</select>
<select id="getTotalAvailableAmount"
resultType="com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAvailableAmountRespVO">
select
sum(amount) as amount,
sum(gift_amount) as giftAmount
from system_organization_amount
where deleted = false
</select>
</mapper>
@@ -1,54 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.cf.imes.module.system.dal.mysql.incomeandexpense.IncomeExpenseDetailsMapper">
<select id="getAccountDetailsPage" resultType="com.cf.imes.module.system.dal.dataobject.incomeandexpense.AccountDetailsDO">
select i.id, i.business_no, i.order_no ,i.trade_type , i.income_expense_type, i.cash_amount_change, i.gift_amount_change, i.creator, i.create_time, i.organ_id ,i.purchase_id,
p.total_amount, p.external_spent, p.account_balance_spent, p.gift_money_spent, p.payment_method, o.channel_code
from income_expense_details i
left join purchase_record p on i.purchase_id = p.id
left join pay_order o on i.order_no = o.id
where i.deleted = false
<if test="reqVO.organId != null">
AND i.organ_id = #{reqVO.organId}
</if>
<if test="reqVO.businessNo != null and reqVO.businessNo != ''">
AND i.business_no like concat('%', #{reqVO.businessNo}, '%')
</if>
<if test="reqVO.orderNo != null and reqVO.orderNo != ''">
AND (i.order_no = #{reqVO.orderNo} or i.purchase_id = #{reqVO.orderNo})
</if>
<if test="reqVO.tradeType != null">
<choose>
<when test="reqVO.tradeType == @com.cf.imes.module.system.enums.pay.TradeTypeEnum@RECHARGE.code">
AND i.trade_type IN (
#{reqVO.tradeType},
'${@com.cf.imes.module.system.enums.pay.TradeTypeEnum@MANUAL_ADJUST.code}'
)
</when>
<otherwise>
AND i.trade_type = #{reqVO.tradeType}
</otherwise>
</choose>
</if>
<if test="reqVO.incomeExpenseType != null">
AND i.income_expense_type = #{reqVO.incomeExpenseType}
</if>
<if test="reqVO.operateTime != null and reqVO.operateTime.length == 2">
AND i.create_time between #{reqVO.operateTime[0]} and #{reqVO.operateTime[1]}
</if>
<if test="reqVO.productPrice != null">
AND p.total_amount = #{reqVO.productPrice}
</if>
<if test="reqVO.rechargeAmount != null">
AND i.cash_amount_change = #{reqVO.rechargeAmount}
AND (i.trade_type = '${@com.cf.imes.module.system.enums.pay.TradeTypeEnum@RECHARGE.code}' or i.trade_type = '${@com.cf.imes.module.system.enums.pay.TradeTypeEnum@MANUAL_ADJUST.code}')
</if>
<if test="reqVO.giftAmount != null">
AND i.gift_amount_change = #{reqVO.giftAmount}
AND (i.trade_type = '${@com.cf.imes.module.system.enums.pay.TradeTypeEnum@RECHARGE.code}' or i.trade_type = '${@com.cf.imes.module.system.enums.pay.TradeTypeEnum@MANUAL_ADJUST.code}')
</if>
<if test="reqVO.operator != null and reqVO.operator !=''">
AND i.creator like concat('%', #{reqVO.operator}, '%')
</if>
</select>
</mapper>
@@ -1,17 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.cf.imes.module.system.dal.mysql.funds.purchase.PurchaseRecordMapper">
<select id="getInvoicingAmount" resultType="java.math.BigDecimal">
SELECT SUM(
CASE
WHEN initial = TRUE THEN total_amount
ELSE account_balance_spent
END
) AS total_spent
FROM purchase_record
where organ_id = #{organId} and is_invocing = '${@com.cf.imes.module.system.enums.pay.InvoiceStatusEnum@INVOICABLE.code}' and deleted = false and initial != true;
</select>
<!-- 查询机构下开票金额统计:可开票、开票中、已开票-->
<select id="getOrgInvoiceAmountStatistics" resultType="com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountRespVO">
SELECT
@@ -55,8 +44,7 @@
<select id="getTotalSales"
resultType="com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO">
select
sum(total_amount - gift_money_spent) as amount,
sum(gift_money_spent) as giftAmount
sum(total_amount) as amount
from purchase_record
where deleted = false and initial != true;
</select>
@@ -71,12 +59,6 @@
and create_time &lt; CURDATE() + INTERVAL 1 DAY;
</select>
<select id="getTotalRechargeUsageAmount" resultType="java.math.BigDecimal">
select sum(account_balance_spent)
from purchase_record
where deleted = false;
</select>
<sql id="dateCreate">
<if test="req.unit != null and req.unit == @com.cf.imes.framework.common.enums.StatisticsUnit@QUARTER.getValue()">
,CONCAT(YEAR(o.create_time), '-', QUARTER(o.create_time)) as date
@@ -1,87 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.manualadjust;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceRespVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceSaveReqVO;
import com.cf.imes.module.system.enums.pay.AdjustTypeEnum;
import com.cf.imes.module.system.service.funds.manualadjust.ManualAdjustAccountBalanceService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import java.math.BigDecimal;
import java.util.Collections;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author Gqr
* @since 2025/10/27 14:31
*/
@WebMvcTest(controllers = ManualAdjustAccountBalanceController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
public class ManualAdjustAccountBalanceControllerTest {
@Autowired
private MockMvc mockMvc;
@MockitoBean
private ManualAdjustAccountBalanceService manualAdjustAccountBalanceService;
@Autowired
private ObjectMapper objectMapper;
@Test
void testCreateAjustment() throws Exception {
ManualAdjustAccountBalanceSaveReqVO reqVO = new ManualAdjustAccountBalanceSaveReqVO();
reqVO.setOrganId(1L);
reqVO.setAdjustType(1);
reqVO.setRechargeAmount(new BigDecimal("100"));
reqVO.setGiftAmount(new BigDecimal("20"));
when(manualAdjustAccountBalanceService.createAjustment(any())).thenReturn(123L);
mockMvc.perform(put("/system/balance/manualadjust")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(reqVO)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data").value(123));
verify(manualAdjustAccountBalanceService).createAjustment(any());
}
@Test
void testGetAdjustPage() throws Exception {
ManualAdjustAccountBalancePageReqVO pageReqVO = new ManualAdjustAccountBalancePageReqVO();
pageReqVO.setPageNo(1);
pageReqVO.setPageSize(10);
ManualAdjustAccountBalanceRespVO respVO = new ManualAdjustAccountBalanceRespVO();
respVO.setOrganName("测试组织");
respVO.setAdjustType(AdjustTypeEnum.INCREASE.getType());
PageResult<ManualAdjustAccountBalanceRespVO> pageResult = new PageResult<>(
Collections.singletonList(respVO), 1L);
when(manualAdjustAccountBalanceService.getPage(any())).thenReturn(pageResult);
mockMvc.perform(get("/system/balance/manualadjust/page")
.param("pageNo", "1")
.param("pageSize", "10"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.list[0].organName").value("测试组织"))
.andExpect(jsonPath("$.data.total").value(1));
verify(manualAdjustAccountBalanceService).getPage(any());
}
}
@@ -0,0 +1,164 @@
//package com.cf.imes.module.system.controller.admin.funds.recharge;
//
//import com.cf.imes.framework.common.pojo.PageResult;
//import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargePageReqVO;
//import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeSaveReqVO;
//import com.cf.imes.module.system.dal.dataobject.funds.recharge.GiftMoneyDetailsDO;
//import com.cf.imes.module.system.enums.recharge.RechargeGiftTypeEnum;
//import com.cf.imes.module.system.enums.recharge.RechargeTypeEnum;
//import com.cf.imes.module.system.service.funds.recharge.RechargeActiveService;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import org.junit.jupiter.api.Test;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
//import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
//import org.springframework.http.MediaType;
//import org.springframework.test.context.bean.override.mockito.MockitoBean;
//import org.springframework.test.web.servlet.MockMvc;
//
//import java.math.BigDecimal;
//import java.time.LocalDateTime;
//import java.util.List;
//
//import static org.mockito.ArgumentMatchers.any;
//import static org.mockito.ArgumentMatchers.anyLong;
//import static org.mockito.Mockito.doNothing;
//import static org.mockito.Mockito.times;
//import static org.mockito.Mockito.verify;
//import static org.mockito.Mockito.when;
//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
//
///**
// * @author Gqr
// * @since 2025/10/27 9:29
// */
//@WebMvcTest(controllers = RechargeActiveController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
//class RechargeActiveControllerTest {
// @Autowired
// private MockMvc mockMvc;
//
// @MockitoBean
// private RechargeActiveService rechargeActiveService;
//
// @Autowired
// private ObjectMapper objectMapper;
//
// @Test
// void testCreateRechargeActive() throws Exception {
// RechargeSaveReqVO vo = new RechargeSaveReqVO();
// vo.setActivityName("充值活动");
// vo.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// vo.setRechargeType(RechargeTypeEnum.ALIPAY.getStatus());
// vo.setRechargeAmount(BigDecimal.valueOf(100));
// vo.setGiftAmount(BigDecimal.valueOf(100));
// LocalDateTime now = LocalDateTime.now();
// vo.setStartTime(now);
// vo.setEndTime(now);
//
// // mock Service 返回
// when(rechargeActiveService.create(any())).thenReturn(100L);
//
// mockMvc.perform(put("/system/recharge-active")
// .contentType(MediaType.APPLICATION_JSON)
// .content(objectMapper.writeValueAsString(vo)))
// .andExpect(status().isOk())
// .andExpect(jsonPath("$.data").value(100));
//
// // 验证 Service 调用
// verify(rechargeActiveService, times(1)).create(any());
// }
//
// @Test
// void testUpdateRechargeActive() throws Exception {
// RechargeSaveReqVO vo = new RechargeSaveReqVO();
// vo.setId(1L);
// vo.setActivityName("更新充值活动");
// vo.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// vo.setRechargeType(RechargeTypeEnum.ALIPAY.getStatus());
// vo.setRechargeAmount(BigDecimal.valueOf(100));
// vo.setGiftAmount(BigDecimal.valueOf(100));
// LocalDateTime now = LocalDateTime.now();
// vo.setStartTime(now);
// vo.setEndTime(now);
//
// // mock Service 返回
// doNothing().when(rechargeActiveService).update(any());
//
// mockMvc.perform(post("/system/recharge-active")
// .contentType(MediaType.APPLICATION_JSON)
// .content(objectMapper.writeValueAsString(vo)))
// .andExpect(status().isOk())
// .andExpect(jsonPath("$.data").value(true));
//
// // 验证 Service 调用
// verify(rechargeActiveService, times(1)).update(any());
// }
//
// @Test
// void testDeleteRechargeActive() throws Exception {
// Long id = 3L;
// doNothing().when(rechargeActiveService).delete(anyLong());
//
// mockMvc.perform(delete("/system/recharge-active/{id}", id))
// .andExpect(status().isOk())
// .andExpect(jsonPath("$.data").value(true));
//
// verify(rechargeActiveService, times(1)).delete(id);
// }
//
// @Test
// void testGetRechargeActive() throws Exception {
// Long id = 123L;
// GiftMoneyDetailsDO mockDO = new GiftMoneyDetailsDO()
// .setId(id);
// when(rechargeActiveService.get(id)).thenReturn(mockDO);
//
// mockMvc.perform(get("/system/recharge-active/{id}", id))
// .andExpect(status().isOk())
// .andExpect(jsonPath("$.data.id").value(123L));
//
// verify(rechargeActiveService, times(1)).get(id);
// }
//
// @Test
// void testGetRechargeActivePage() throws Exception {
// RechargePageReqVO reqVO = new RechargePageReqVO();
// PageResult<GiftMoneyDetailsDO> mockPage = new PageResult<>();
// mockPage.setTotal(1L);
// mockPage.setList(List.of(new GiftMoneyDetailsDO().setId(1L)));
// when(rechargeActiveService.getPage(any())).thenReturn(mockPage);
//
// mockMvc.perform(get("/system/recharge-active/page")
// .contentType(MediaType.APPLICATION_JSON)
// .content(objectMapper.writeValueAsString(reqVO)))
// .andExpect(status().isOk())
// .andExpect(jsonPath("$.data.list[0].id").value(1L));
//
// verify(rechargeActiveService, times(1)).getPage(any());
// }
//
// @Test
// void testGetAvailableRechargeActivePage_success() throws Exception {
// // 模拟 service 返回数据
// GiftMoneyDetailsDO mockDO = new GiftMoneyDetailsDO();
// mockDO.setId(1L);
// mockDO.setRechargeAmount(new BigDecimal("50.00"));
// mockDO.setActivityName("新人充值活动");
//
// when(rechargeActiveService.getAvailableRechargeActiveList())
// .thenReturn(List.of(mockDO));
//
// // 发起请求
// mockMvc.perform(get("/system/recharge-active/available")
// .contentType(MediaType.APPLICATION_JSON))
// .andExpect(status().isOk())
// .andExpect(jsonPath("$.code").value(0)) // CommonResult.success 通常 code=0
// .andExpect(jsonPath("$.data[0].activityName").value("新人充值活动"))
// .andExpect(jsonPath("$.data[0].rechargeAmount").value(50.00));
// }
//}
@@ -1,164 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.recharge;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.recharge.GiftMoneyDetailsDO;
import com.cf.imes.module.system.enums.recharge.RechargeGiftTypeEnum;
import com.cf.imes.module.system.enums.recharge.RechargeTypeEnum;
import com.cf.imes.module.system.service.funds.recharge.RechargeActiveService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author Gqr
* @since 2025/10/27 9:29
*/
@WebMvcTest(controllers = RechargeActiveController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
class RechargeActiveControllerTest {
@Autowired
private MockMvc mockMvc;
@MockitoBean
private RechargeActiveService rechargeActiveService;
@Autowired
private ObjectMapper objectMapper;
@Test
void testCreateRechargeActive() throws Exception {
RechargeSaveReqVO vo = new RechargeSaveReqVO();
vo.setActivityName("充值活动");
vo.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
vo.setRechargeType(RechargeTypeEnum.ALIPAY.getStatus());
vo.setRechargeAmount(BigDecimal.valueOf(100));
vo.setGiftAmount(BigDecimal.valueOf(100));
LocalDateTime now = LocalDateTime.now();
vo.setStartTime(now);
vo.setEndTime(now);
// mock Service 返回
when(rechargeActiveService.create(any())).thenReturn(100L);
mockMvc.perform(put("/system/recharge-active")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(vo)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data").value(100));
// 验证 Service 调用
verify(rechargeActiveService, times(1)).create(any());
}
@Test
void testUpdateRechargeActive() throws Exception {
RechargeSaveReqVO vo = new RechargeSaveReqVO();
vo.setId(1L);
vo.setActivityName("更新充值活动");
vo.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
vo.setRechargeType(RechargeTypeEnum.ALIPAY.getStatus());
vo.setRechargeAmount(BigDecimal.valueOf(100));
vo.setGiftAmount(BigDecimal.valueOf(100));
LocalDateTime now = LocalDateTime.now();
vo.setStartTime(now);
vo.setEndTime(now);
// mock Service 返回
doNothing().when(rechargeActiveService).update(any());
mockMvc.perform(post("/system/recharge-active")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(vo)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data").value(true));
// 验证 Service 调用
verify(rechargeActiveService, times(1)).update(any());
}
@Test
void testDeleteRechargeActive() throws Exception {
Long id = 3L;
doNothing().when(rechargeActiveService).delete(anyLong());
mockMvc.perform(delete("/system/recharge-active/{id}", id))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data").value(true));
verify(rechargeActiveService, times(1)).delete(id);
}
@Test
void testGetRechargeActive() throws Exception {
Long id = 123L;
GiftMoneyDetailsDO mockDO = new GiftMoneyDetailsDO()
.setId(id);
when(rechargeActiveService.get(id)).thenReturn(mockDO);
mockMvc.perform(get("/system/recharge-active/{id}", id))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.id").value(123L));
verify(rechargeActiveService, times(1)).get(id);
}
@Test
void testGetRechargeActivePage() throws Exception {
RechargePageReqVO reqVO = new RechargePageReqVO();
PageResult<GiftMoneyDetailsDO> mockPage = new PageResult<>();
mockPage.setTotal(1L);
mockPage.setList(List.of(new GiftMoneyDetailsDO().setId(1L)));
when(rechargeActiveService.getPage(any())).thenReturn(mockPage);
mockMvc.perform(get("/system/recharge-active/page")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(reqVO)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.list[0].id").value(1L));
verify(rechargeActiveService, times(1)).getPage(any());
}
@Test
void testGetAvailableRechargeActivePage_success() throws Exception {
// 模拟 service 返回数据
GiftMoneyDetailsDO mockDO = new GiftMoneyDetailsDO();
mockDO.setId(1L);
mockDO.setRechargeAmount(new BigDecimal("50.00"));
mockDO.setActivityName("新人充值活动");
when(rechargeActiveService.getAvailableRechargeActiveList())
.thenReturn(List.of(mockDO));
// 发起请求
mockMvc.perform(get("/system/recharge-active/available")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(0)) // CommonResult.success 通常 code=0
.andExpect(jsonPath("$.data[0].activityName").value("新人充值活动"))
.andExpect(jsonPath("$.data[0].rechargeAmount").value(50.00));
}
}
@@ -1,55 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.recharge;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsBalanceInfoRespVO;
import com.cf.imes.module.system.service.funds.recharge.RechargeDetailsService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import java.math.BigDecimal;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author Gqr
* @since 2025/10/27 10:56
*/
@WebMvcTest(controllers = RechargeDetailsController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
class RechargeDetailsControllerTest {
@Autowired
private MockMvc mockMvc;
@MockitoBean
private RechargeDetailsService rechargeDetailsService;
@Test
void testGetManageRechargeDetailsBalanceInfo_success() throws Exception {
// 构造 mock 返回对象
RechargeDetailsBalanceInfoRespVO respVO = new RechargeDetailsBalanceInfoRespVO();
respVO.setRechargeAmount(new BigDecimal("100.00"));
respVO.setRechargeUsageAmount(new BigDecimal("60.00"));
when(rechargeDetailsService.getManageRechargeDetailsBalanceInfo()).thenReturn(respVO);
// 执行 GET /recharge/balance
mockMvc.perform(get("/system/rechargeDetails/balance")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(0)) // CommonResult.success 通常 code = 0
.andExpect(jsonPath("$.data.rechargeAmount").value(100.00))
.andExpect(jsonPath("$.data.rechargeUsageAmount").value(60.00));
// 验证 Service 调用
verify(rechargeDetailsService, times(1)).getManageRechargeDetailsBalanceInfo();
}
}
@@ -1,295 +0,0 @@
package com.cf.imes.module.system.service.funds.manualadjust;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.id.core.util.SnowflakeSerialNoWorker3rd;
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceRespVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceSaveReqVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganRechargeAmountRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.organamount.OrganAmountDO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderDO;
import com.cf.imes.module.system.enums.pay.AdjustTypeEnum;
import com.cf.imes.module.system.framework.snowflake.config.MybatisIdProperties;
import com.cf.imes.module.system.service.funds.incomeandexpense.IncomeExpenseService;
import com.cf.imes.module.system.service.funds.organamount.OrganAmountService;
import com.cf.imes.module.system.service.organ.OrganService;
import com.cf.imes.module.system.service.pay.PayOrderService;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import java.math.BigDecimal;
import java.util.Collections;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAMOUNT_GIFT_INSUFFICIENT_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAMOUNT_RECHARGE_INSUFFICIENT_ERROR;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Gqr
* @since 2025/10/27 11:57
*/
@Import(ManualAdjustAccountBalanceServiceImpl.class)
public class ManualAdjustAccountBalanceServiceImplTest extends BaseDbAndRedisUnitTest {
@Resource
private ManualAdjustAccountBalanceService manualAdjustAccountBalanceService;
@MockitoBean
private OrganService organService;
@MockitoBean
private OrganAmountService organAmountService;
@MockitoBean
private IncomeExpenseService incomeExpenseService;
@MockitoBean
private MybatisIdProperties mybatisIdProperties;
@MockitoBean
private PayOrderService payOrderService;
@MockitoBean
private SnowflakeSerialNoWorker3rd snowflakeSerialNoWorker3rd;
@BeforeEach
void setUp() {
when(mybatisIdProperties.getWorkerId()).thenReturn(1L);
when(mybatisIdProperties.getDatacenterId()).thenReturn(1L);
when(snowflakeSerialNoWorker3rd.nextSerialNo()).thenReturn("SN-001");
}
@Test
void testCreateAdjustment_Increase() {
// 模拟请求参数(调增)
ManualAdjustAccountBalanceSaveReqVO reqVO = new ManualAdjustAccountBalanceSaveReqVO();
reqVO.setOrganId(100L);
reqVO.setAdjustType(AdjustTypeEnum.INCREASE.getType());
reqVO.setRechargeAmount(new BigDecimal("100.00"));
reqVO.setGiftAmount(new BigDecimal("20.00"));
reqVO.setRemark("调增测试");
// 模拟依赖返回
OrganAmountDO organAmountDO = new OrganAmountDO();
organAmountDO.setAmount(new BigDecimal("500.00"));
organAmountDO.setGiftAmount(new BigDecimal("100.00"));
when(organAmountService.validOrganAmount(100L)).thenReturn(organAmountDO);
OrganRechargeAmountRespVO rechargeRespVO = new OrganRechargeAmountRespVO();
rechargeRespVO.setAmount(new BigDecimal("600.00"));
rechargeRespVO.setGiftAmount(new BigDecimal("120.00"));
rechargeRespVO.setAvailableAmount(new BigDecimal("720.00"));
when(organAmountService.recharge(eq(100L), any(), any())).thenReturn(rechargeRespVO);
when(incomeExpenseService.createDetail(any())).thenReturn(1L);
// 执行方法
Long result = manualAdjustAccountBalanceService.createAjustment(reqVO);
// 验证逻辑
assertEquals(1L, result);
verify(organService).validOrgan(100L);
verify(payOrderService).createPayOrder(any(PayOrderDO.class));
verify(incomeExpenseService).createDetail(any(IncomeExpenseDetailsDO.class));
}
@Test
void testCreateAdjustment_Decrease() {
// 模拟请求参数(调减)
ManualAdjustAccountBalanceSaveReqVO reqVO = new ManualAdjustAccountBalanceSaveReqVO();
reqVO.setOrganId(200L);
reqVO.setAdjustType(AdjustTypeEnum.DECREASE.getType());
reqVO.setRechargeAmount(new BigDecimal("50.00"));
reqVO.setGiftAmount(new BigDecimal("10.00"));
reqVO.setRemark("调减测试");
// 模拟依赖返回
OrganAmountDO organAmountDO = new OrganAmountDO();
organAmountDO.setAmount(new BigDecimal("500.00"));
organAmountDO.setGiftAmount(new BigDecimal("100.00"));
when(organAmountService.validOrganAmount(200L)).thenReturn(organAmountDO);
OrganRechargeAmountRespVO rechargeRespVO = new OrganRechargeAmountRespVO();
rechargeRespVO.setAmount(new BigDecimal("450.00"));
rechargeRespVO.setGiftAmount(new BigDecimal("90.00"));
rechargeRespVO.setAvailableAmount(new BigDecimal("540.00"));
when(organAmountService.recharge(eq(200L), any(), any())).thenReturn(rechargeRespVO);
when(incomeExpenseService.createDetail(any())).thenReturn(2L);
// 执行方法
Long result = manualAdjustAccountBalanceService.createAjustment(reqVO);
// 验证逻辑
assertEquals(2L, result);
verify(organService).validOrgan(200L);
verify(payOrderService).createPayOrder(any(PayOrderDO.class));
verify(incomeExpenseService).createDetail(any(IncomeExpenseDetailsDO.class));
}
@Test
void testCreateAdjustment_Decrease_RechargeInsufficient() {
// given
ManualAdjustAccountBalanceSaveReqVO reqVO = new ManualAdjustAccountBalanceSaveReqVO();
reqVO.setOrganId(300L);
reqVO.setAdjustType(AdjustTypeEnum.DECREASE.getType());
reqVO.setRechargeAmount(new BigDecimal("200.00")); // 想减200
reqVO.setGiftAmount(null);
OrganAmountDO organAmountDO = new OrganAmountDO();
organAmountDO.setAmount(new BigDecimal("100.00")); // 实际余额只有100,不够减
organAmountDO.setGiftAmount(new BigDecimal("50.00"));
when(organAmountService.validOrganAmount(300L)).thenReturn(organAmountDO);
// 余额不足
assertServiceException(() -> manualAdjustAccountBalanceService.createAjustment(reqVO), ORGAMOUNT_RECHARGE_INSUFFICIENT_ERROR);
}
@Test
void testCreateAdjustment_Decrease_GiftInsufficient() {
// given
ManualAdjustAccountBalanceSaveReqVO reqVO = new ManualAdjustAccountBalanceSaveReqVO();
reqVO.setOrganId(400L);
reqVO.setAdjustType(AdjustTypeEnum.DECREASE.getType());
reqVO.setRechargeAmount(null);
reqVO.setGiftAmount(new BigDecimal("30.00")); // 想减30赠送金
OrganAmountDO organAmountDO = new OrganAmountDO();
organAmountDO.setAmount(new BigDecimal("100.00"));
organAmountDO.setGiftAmount(new BigDecimal("10.00")); // 实际赠送金只有10,不够减
when(organAmountService.validOrganAmount(400L)).thenReturn(organAmountDO);
// 赠送金不足
assertServiceException(() -> manualAdjustAccountBalanceService.createAjustment(reqVO), ORGAMOUNT_GIFT_INSUFFICIENT_ERROR);
}
@Test
void testCreateAdjustment_Decrease_GiftAmountNull() {
// given
ManualAdjustAccountBalanceSaveReqVO reqVO = new ManualAdjustAccountBalanceSaveReqVO();
reqVO.setOrganId(600L);
reqVO.setAdjustType(AdjustTypeEnum.DECREASE.getType());
reqVO.setRechargeAmount(new BigDecimal("50.00")); // 有充值金额
reqVO.setGiftAmount(null); // giftAmount 为 null
OrganAmountDO organAmountDO = new OrganAmountDO();
organAmountDO.setAmount(new BigDecimal("100.00"));
organAmountDO.setGiftAmount(new BigDecimal("100.00"));
when(organAmountService.validOrganAmount(600L)).thenReturn(organAmountDO);
OrganRechargeAmountRespVO respVO = new OrganRechargeAmountRespVO();
respVO.setAmount(new BigDecimal("50.00"));
respVO.setGiftAmount(new BigDecimal("100.00"));
respVO.setAvailableAmount(new BigDecimal("150.00"));
when(organAmountService.recharge(eq(600L), any(), any())).thenReturn(respVO);
when(incomeExpenseService.createDetail(any())).thenReturn(10L);
// when
Long result = manualAdjustAccountBalanceService.createAjustment(reqVO);
// then
assertEquals(10L, result);
verify(payOrderService).createPayOrder(any(PayOrderDO.class));
verify(incomeExpenseService).createDetail(any(IncomeExpenseDetailsDO.class));
}
@Test
void testCreateAdjustment_Decrease_RechargeAmountNull() {
// given
ManualAdjustAccountBalanceSaveReqVO reqVO = new ManualAdjustAccountBalanceSaveReqVO();
reqVO.setOrganId(600L);
reqVO.setAdjustType(AdjustTypeEnum.DECREASE.getType());
reqVO.setRechargeAmount(null); // rechargeAmount 为 null
reqVO.setGiftAmount(new BigDecimal("50.00"));
OrganAmountDO organAmountDO = new OrganAmountDO();
organAmountDO.setAmount(new BigDecimal("100.00"));
organAmountDO.setGiftAmount(new BigDecimal("100.00"));
when(organAmountService.validOrganAmount(600L)).thenReturn(organAmountDO);
OrganRechargeAmountRespVO respVO = new OrganRechargeAmountRespVO();
respVO.setAmount(new BigDecimal("50.00"));
respVO.setGiftAmount(new BigDecimal("100.00"));
respVO.setAvailableAmount(new BigDecimal("150.00"));
when(organAmountService.recharge(eq(600L), any(), any())).thenReturn(respVO);
when(incomeExpenseService.createDetail(any())).thenReturn(10L);
// when
Long result = manualAdjustAccountBalanceService.createAjustment(reqVO);
// then
assertEquals(10L, result);
verify(payOrderService, never()).createPayOrder(any(PayOrderDO.class));
verify(incomeExpenseService).createDetail(any(IncomeExpenseDetailsDO.class));
}
@Test
void testGetPage_WithNonNullOrgan() {
// given
ManualAdjustAccountBalancePageReqVO pageReqVO = new ManualAdjustAccountBalancePageReqVO();
IncomeExpenseDetailsDO detailsDO = new IncomeExpenseDetailsDO();
detailsDO.setIncomeExpenseType(AdjustTypeEnum.INCREASE.getType()); // 假设 1 -> 调增
detailsDO.setOrganId(100L);
PageResult<IncomeExpenseDetailsDO> mockPageResult = new PageResult<>(Collections.singletonList(detailsDO), 1L);
when(incomeExpenseService.selectAdjustPage(pageReqVO)).thenReturn(mockPageResult);
OrganizationDO organ = new OrganizationDO();
organ.setName("测试组织");
when(organService.getOrganWithDeleted(100L)).thenReturn(organ);
// when
PageResult<ManualAdjustAccountBalanceRespVO> result = manualAdjustAccountBalanceService.getPage(pageReqVO);
// then
assertEquals(1, result.getList().size());
ManualAdjustAccountBalanceRespVO respVO = result.getList().get(0);
assertEquals("测试组织", respVO.getOrganName());
assertEquals(AdjustTypeEnum.INCREASE.getType(), respVO.getAdjustType());
verify(incomeExpenseService).selectAdjustPage(pageReqVO);
verify(organService).getOrganWithDeleted(100L);
}
@Test
void testGetPage_WithNullOrgan() {
// given
ManualAdjustAccountBalancePageReqVO pageReqVO = new ManualAdjustAccountBalancePageReqVO();
IncomeExpenseDetailsDO detailsDO = new IncomeExpenseDetailsDO();
detailsDO.setIncomeExpenseType(AdjustTypeEnum.DECREASE.getType()); // 假设 2 -> 调减
detailsDO.setOrganId(200L);
PageResult<IncomeExpenseDetailsDO> mockPageResult = new PageResult<>(Collections.singletonList(detailsDO), 1L);
when(incomeExpenseService.selectAdjustPage(pageReqVO)).thenReturn(mockPageResult);
// 模拟组织为 null,覆盖 if 条件 false
when(organService.getOrganWithDeleted(200L)).thenReturn(null);
// when
PageResult<ManualAdjustAccountBalanceRespVO> result = manualAdjustAccountBalanceService.getPage(pageReqVO);
// then
assertEquals(1, result.getList().size());
ManualAdjustAccountBalanceRespVO respVO = result.getList().get(0);
assertNull(respVO.getOrganName());
assertEquals(AdjustTypeEnum.DECREASE.getType(), respVO.getAdjustType());
verify(incomeExpenseService).selectAdjustPage(pageReqVO);
verify(organService).getOrganWithDeleted(200L);
}
}
@@ -0,0 +1,252 @@
//package com.cf.imes.module.system.service.funds.recharge;
//
//import cn.hutool.core.bean.BeanUtil;
//import com.cf.imes.framework.common.pojo.PageResult;
//import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
//import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargePageReqVO;
//import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeSaveReqVO;
//import com.cf.imes.module.system.dal.dataobject.funds.recharge.GiftMoneyDetailsDO;
//import com.cf.imes.module.system.dal.mysql.funds.recharge.GiftMoneyDetailsMapper;
//import com.cf.imes.module.system.enums.recharge.RechargeGiftTypeEnum;
//import com.cf.imes.module.system.enums.recharge.RechargeTypeEnum;
//import jakarta.annotation.Resource;
//import org.junit.jupiter.api.MethodOrderer;
//import org.junit.jupiter.api.Order;
//import org.junit.jupiter.api.Test;
//import org.junit.jupiter.api.TestMethodOrder;
//import org.springframework.context.annotation.Import;
//
//import java.math.BigDecimal;
//import java.time.LocalDateTime;
//import java.util.List;
//
//import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId;
//import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
//import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
//import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo;
//import static com.cf.imes.module.system.enums.ErrorCodeConstants.RECHARGE_ACTIVE_NAME_IS_EXIST;
//import static com.cf.imes.module.system.enums.ErrorCodeConstants.RECHARGE_ACTIVE_NO_EXIST;
//import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
//import static org.junit.jupiter.api.Assertions.assertEquals;
//import static org.junit.jupiter.api.Assertions.assertNotNull;
//
///**
// * @author Gqr
// * @since 2025/10/24 11:20
// */
//@Import(RechargeActiveServiceImpl.class)
//@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
//class RechargeActiveServiceImplTest extends BaseDbAndRedisUnitTest {
// @Resource
// private RechargeActiveService rechargeActiveService;
//
// @Resource
// private GiftMoneyDetailsMapper giftMoneyDetailsMapper;
//
// private static GiftMoneyDetailsDO createDO;
//
// @Test
// @Order(1)
// void testCreate() {
// RechargeSaveReqVO reqVO = randomPojo(RechargeSaveReqVO.class, o -> {
// o.setId(null);
// o.setActivityName("充值送活动");
// o.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// o.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
// o.setRechargeAmount(BigDecimal.valueOf(100));
// o.setGiftAmount(BigDecimal.valueOf(20));
// });
//
// Long id = rechargeActiveService.create(reqVO);
//
// // 校验数据库插入结果
// createDO = giftMoneyDetailsMapper.selectById(id);
// assertNotNull(createDO);
// assertEquals("充值送活动", createDO.getActivityName());
// assertEquals(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus(), createDO.getRechargeType());
// assertEquals(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus(), createDO.getRechargeGiftType());
// assertEquals(new BigDecimal("100.000"), createDO.getRechargeAmount());
// assertEquals(new BigDecimal("20.000"), createDO.getGiftAmount());
//
// // 再次插入相同活动名称,断言异常
// assertServiceException(() -> rechargeActiveService.create(reqVO),
// RECHARGE_ACTIVE_NAME_IS_EXIST);
// }
//
// @Test
// @Order(2)
// void testUpdate_not_exist() {
// RechargeSaveReqVO reqVO = new RechargeSaveReqVO();
// reqVO.setId(321L);
//
// assertServiceException(() -> rechargeActiveService.update(reqVO),
// RECHARGE_ACTIVE_NO_EXIST);
//
// reqVO.setId(null);
//
// assertServiceException(() -> rechargeActiveService.update(reqVO),
// RECHARGE_ACTIVE_NO_EXIST);
// }
//
// @Test
// @Order(2)
// void testUpdate() {
//
// // 插入
// createDO.setId(null);
// createDO.setActivityName("充值送活动新");
// createDO.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// createDO.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
// createDO.setRechargeAmount(BigDecimal.valueOf(100));
// createDO.setGiftAmount(BigDecimal.valueOf(20));
// giftMoneyDetailsMapper.insert(createDO);
//
// RechargeSaveReqVO reqVO = new RechargeSaveReqVO();
// reqVO.setId(createDO.getId());
// reqVO.setActivityName("充值送活动");
// assertServiceException(() -> rechargeActiveService.update(reqVO),
// RECHARGE_ACTIVE_NAME_IS_EXIST);
//
// // 更新成功
// RechargeSaveReqVO update = BeanUtil.copyProperties(createDO, RechargeSaveReqVO.class);
// assertDoesNotThrow(() -> rechargeActiveService.update(update));
// }
//
//
//
// @Test
// @Order(3)
// void testGet_not_exist() {
// assertServiceException(() -> rechargeActiveService.get(null), RECHARGE_ACTIVE_NO_EXIST);
// }
//
// @Test
// @Order(4)
// void testGet() {
// assertNotNull(rechargeActiveService.getDefaultNull(createDO.getId()));
// }
//
// @Test
// @Order(5)
// void testGetPage_success() {
// GiftMoneyDetailsDO detail = randomPojo(GiftMoneyDetailsDO.class, o -> {
// o.setId(null);
// o.setActivityName("晨丰分页活动");
// o.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// o.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
// o.setRechargeAmount(BigDecimal.valueOf(100).setScale(3));
// o.setGiftAmount(BigDecimal.valueOf(20).setScale(3));
// });
//
// giftMoneyDetailsMapper.insert(detail);
//
// // 不匹配 ActivityName
// giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setActivityName("新分页活动")));
//
// // 不匹配 RechargeGiftType
// giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setRechargeGiftType(RechargeGiftTypeEnum.FULL_X_GIVE_X.getStatus())));
//
// // 不匹配 GiftAmount
// giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setGiftAmount(BigDecimal.valueOf(99))));
//
// // 不匹配 RechargeAmount
// giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setRechargeAmount(BigDecimal.valueOf(99))));
//
// // 被逻辑删除
// giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setDeleted(true)));
//
// // ============ 构造查询参数 ============
// RechargePageReqVO reqVO = new RechargePageReqVO();
// reqVO.setActivityName("晨丰");
// reqVO.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// reqVO.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
// reqVO.setRechargeAmount(BigDecimal.valueOf(100));
// reqVO.setGiftAmount(BigDecimal.valueOf(20));
// reqVO.setPageNo(1);
// reqVO.setPageSize(10);
//
// // ============ 调用方法 ============
// PageResult<GiftMoneyDetailsDO> pageResult = rechargeActiveService.getPage(reqVO);
//
// // ============ 断言结果 ============
// assertEquals(1, pageResult.getTotal(), "分页结果数量应为1");
// assertEquals(1, pageResult.getList().size(), "分页列表长度应为1");
// assertPojoEquals(detail, pageResult.getList().get(0));
// }
//
// @Test
// @Order(6)
// void testDelete() {
// assertDoesNotThrow(() -> rechargeActiveService.delete(createDO.getId()));
// }
//
// @Test
// @Order(7)
// void testDelete_not_exist() {
// assertServiceException(() -> rechargeActiveService.delete(null), RECHARGE_ACTIVE_NO_EXIST);
// assertServiceException(() -> rechargeActiveService.delete(321L), RECHARGE_ACTIVE_NO_EXIST);
// }
//
// @Test
// @Order(8)
// void testGetAvailableRechargeActiveList() {
// // 当前时间
// LocalDateTime now = LocalDateTime.now();
//
// // 1️⃣ 有效活动(时间区间内)
// GiftMoneyDetailsDO valid = new GiftMoneyDetailsDO();
// valid.setActivityName("有效活动");
// valid.setRechargeAmount(new java.math.BigDecimal("100.000"));
// valid.setGiftAmount(new java.math.BigDecimal("10.000"));
// valid.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// valid.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
// valid.setStartTime(now.minusDays(1));
// valid.setEndTime(now.plusDays(1));
// valid.setDeleted(false);
// giftMoneyDetailsMapper.insert(valid);
//
// // 2️⃣ 未开始活动
// GiftMoneyDetailsDO notStarted = new GiftMoneyDetailsDO();
// notStarted.setActivityName("未开始活动");
// notStarted.setRechargeAmount(new java.math.BigDecimal("100.000"));
// notStarted.setGiftAmount(new java.math.BigDecimal("10.000"));
// notStarted.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// notStarted.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
// notStarted.setStartTime(now.plusDays(1));
// notStarted.setEndTime(now.plusDays(2));
// notStarted.setDeleted(false);
// giftMoneyDetailsMapper.insert(notStarted);
//
// // 3️⃣ 已过期活动
// GiftMoneyDetailsDO expired = new GiftMoneyDetailsDO();
// expired.setActivityName("已过期活动");
// expired.setRechargeAmount(new java.math.BigDecimal("100.000"));
// expired.setGiftAmount(new java.math.BigDecimal("10.000"));
// expired.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// expired.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
// expired.setStartTime(now.minusDays(5));
// expired.setEndTime(now.minusDays(1));
// expired.setDeleted(false);
// giftMoneyDetailsMapper.insert(expired);
//
// // 4️⃣ 被逻辑删除的活动
// GiftMoneyDetailsDO deleted = new GiftMoneyDetailsDO();
// deleted.setActivityName("被删除活动");
// deleted.setRechargeAmount(new java.math.BigDecimal("100.000"));
// deleted.setGiftAmount(new java.math.BigDecimal("10.000"));
// deleted.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
// deleted.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
// deleted.setStartTime(now.minusDays(1));
// deleted.setEndTime(now.plusDays(1));
// deleted.setDeleted(true);
// giftMoneyDetailsMapper.insert(deleted);
//
// // 执行被测方法
// List<GiftMoneyDetailsDO> result = rechargeActiveService.getAvailableRechargeActiveList();
//
// // 验证结果
// assertEquals(1, result.size(), "只应返回一个有效活动");
// assertEquals("有效活动", result.get(0).getActivityName());
// }
//
//}
@@ -1,252 +0,0 @@
package com.cf.imes.module.system.service.funds.recharge;
import cn.hutool.core.bean.BeanUtil;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.recharge.GiftMoneyDetailsDO;
import com.cf.imes.module.system.dal.mysql.funds.recharge.GiftMoneyDetailsMapper;
import com.cf.imes.module.system.enums.recharge.RechargeGiftTypeEnum;
import com.cf.imes.module.system.enums.recharge.RechargeTypeEnum;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.context.annotation.Import;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.RECHARGE_ACTIVE_NAME_IS_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.RECHARGE_ACTIVE_NO_EXIST;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* @author Gqr
* @since 2025/10/24 11:20
*/
@Import(RechargeActiveServiceImpl.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class RechargeActiveServiceImplTest extends BaseDbAndRedisUnitTest {
@Resource
private RechargeActiveService rechargeActiveService;
@Resource
private GiftMoneyDetailsMapper giftMoneyDetailsMapper;
private static GiftMoneyDetailsDO createDO;
@Test
@Order(1)
void testCreate() {
RechargeSaveReqVO reqVO = randomPojo(RechargeSaveReqVO.class, o -> {
o.setId(null);
o.setActivityName("充值送活动");
o.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
o.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
o.setRechargeAmount(BigDecimal.valueOf(100));
o.setGiftAmount(BigDecimal.valueOf(20));
});
Long id = rechargeActiveService.create(reqVO);
// 校验数据库插入结果
createDO = giftMoneyDetailsMapper.selectById(id);
assertNotNull(createDO);
assertEquals("充值送活动", createDO.getActivityName());
assertEquals(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus(), createDO.getRechargeType());
assertEquals(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus(), createDO.getRechargeGiftType());
assertEquals(new BigDecimal("100.000"), createDO.getRechargeAmount());
assertEquals(new BigDecimal("20.000"), createDO.getGiftAmount());
// 再次插入相同活动名称,断言异常
assertServiceException(() -> rechargeActiveService.create(reqVO),
RECHARGE_ACTIVE_NAME_IS_EXIST);
}
@Test
@Order(2)
void testUpdate_not_exist() {
RechargeSaveReqVO reqVO = new RechargeSaveReqVO();
reqVO.setId(321L);
assertServiceException(() -> rechargeActiveService.update(reqVO),
RECHARGE_ACTIVE_NO_EXIST);
reqVO.setId(null);
assertServiceException(() -> rechargeActiveService.update(reqVO),
RECHARGE_ACTIVE_NO_EXIST);
}
@Test
@Order(2)
void testUpdate() {
// 插入
createDO.setId(null);
createDO.setActivityName("充值送活动新");
createDO.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
createDO.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
createDO.setRechargeAmount(BigDecimal.valueOf(100));
createDO.setGiftAmount(BigDecimal.valueOf(20));
giftMoneyDetailsMapper.insert(createDO);
RechargeSaveReqVO reqVO = new RechargeSaveReqVO();
reqVO.setId(createDO.getId());
reqVO.setActivityName("充值送活动");
assertServiceException(() -> rechargeActiveService.update(reqVO),
RECHARGE_ACTIVE_NAME_IS_EXIST);
// 更新成功
RechargeSaveReqVO update = BeanUtil.copyProperties(createDO, RechargeSaveReqVO.class);
assertDoesNotThrow(() -> rechargeActiveService.update(update));
}
@Test
@Order(3)
void testGet_not_exist() {
assertServiceException(() -> rechargeActiveService.get(null), RECHARGE_ACTIVE_NO_EXIST);
}
@Test
@Order(4)
void testGet() {
assertNotNull(rechargeActiveService.getDefaultNull(createDO.getId()));
}
@Test
@Order(5)
void testGetPage_success() {
GiftMoneyDetailsDO detail = randomPojo(GiftMoneyDetailsDO.class, o -> {
o.setId(null);
o.setActivityName("晨丰分页活动");
o.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
o.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
o.setRechargeAmount(BigDecimal.valueOf(100).setScale(3));
o.setGiftAmount(BigDecimal.valueOf(20).setScale(3));
});
giftMoneyDetailsMapper.insert(detail);
// 不匹配 ActivityName
giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setActivityName("新分页活动")));
// 不匹配 RechargeGiftType
giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setRechargeGiftType(RechargeGiftTypeEnum.FULL_X_GIVE_X.getStatus())));
// 不匹配 GiftAmount
giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setGiftAmount(BigDecimal.valueOf(99))));
// 不匹配 RechargeAmount
giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setRechargeAmount(BigDecimal.valueOf(99))));
// 被逻辑删除
giftMoneyDetailsMapper.insert(cloneIgnoreId(detail, o -> o.setDeleted(true)));
// ============ 构造查询参数 ============
RechargePageReqVO reqVO = new RechargePageReqVO();
reqVO.setActivityName("晨丰");
reqVO.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
reqVO.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
reqVO.setRechargeAmount(BigDecimal.valueOf(100));
reqVO.setGiftAmount(BigDecimal.valueOf(20));
reqVO.setPageNo(1);
reqVO.setPageSize(10);
// ============ 调用方法 ============
PageResult<GiftMoneyDetailsDO> pageResult = rechargeActiveService.getPage(reqVO);
// ============ 断言结果 ============
assertEquals(1, pageResult.getTotal(), "分页结果数量应为1");
assertEquals(1, pageResult.getList().size(), "分页列表长度应为1");
assertPojoEquals(detail, pageResult.getList().get(0));
}
@Test
@Order(6)
void testDelete() {
assertDoesNotThrow(() -> rechargeActiveService.delete(createDO.getId()));
}
@Test
@Order(7)
void testDelete_not_exist() {
assertServiceException(() -> rechargeActiveService.delete(null), RECHARGE_ACTIVE_NO_EXIST);
assertServiceException(() -> rechargeActiveService.delete(321L), RECHARGE_ACTIVE_NO_EXIST);
}
@Test
@Order(8)
void testGetAvailableRechargeActiveList() {
// 当前时间
LocalDateTime now = LocalDateTime.now();
// 1️⃣ 有效活动(时间区间内)
GiftMoneyDetailsDO valid = new GiftMoneyDetailsDO();
valid.setActivityName("有效活动");
valid.setRechargeAmount(new java.math.BigDecimal("100.000"));
valid.setGiftAmount(new java.math.BigDecimal("10.000"));
valid.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
valid.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
valid.setStartTime(now.minusDays(1));
valid.setEndTime(now.plusDays(1));
valid.setDeleted(false);
giftMoneyDetailsMapper.insert(valid);
// 2️⃣ 未开始活动
GiftMoneyDetailsDO notStarted = new GiftMoneyDetailsDO();
notStarted.setActivityName("未开始活动");
notStarted.setRechargeAmount(new java.math.BigDecimal("100.000"));
notStarted.setGiftAmount(new java.math.BigDecimal("10.000"));
notStarted.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
notStarted.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
notStarted.setStartTime(now.plusDays(1));
notStarted.setEndTime(now.plusDays(2));
notStarted.setDeleted(false);
giftMoneyDetailsMapper.insert(notStarted);
// 3️⃣ 已过期活动
GiftMoneyDetailsDO expired = new GiftMoneyDetailsDO();
expired.setActivityName("已过期活动");
expired.setRechargeAmount(new java.math.BigDecimal("100.000"));
expired.setGiftAmount(new java.math.BigDecimal("10.000"));
expired.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
expired.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
expired.setStartTime(now.minusDays(5));
expired.setEndTime(now.minusDays(1));
expired.setDeleted(false);
giftMoneyDetailsMapper.insert(expired);
// 4️⃣ 被逻辑删除的活动
GiftMoneyDetailsDO deleted = new GiftMoneyDetailsDO();
deleted.setActivityName("被删除活动");
deleted.setRechargeAmount(new java.math.BigDecimal("100.000"));
deleted.setGiftAmount(new java.math.BigDecimal("10.000"));
deleted.setRechargeGiftType(RechargeGiftTypeEnum.EVERY_X_GIVE_X.getStatus());
deleted.setRechargeType(RechargeTypeEnum.WECHAT_AND_ALIPAY.getStatus());
deleted.setStartTime(now.minusDays(1));
deleted.setEndTime(now.plusDays(1));
deleted.setDeleted(true);
giftMoneyDetailsMapper.insert(deleted);
// 执行被测方法
List<GiftMoneyDetailsDO> result = rechargeActiveService.getAvailableRechargeActiveList();
// 验证结果
assertEquals(1, result.size(), "只应返回一个有效活动");
assertEquals("有效活动", result.get(0).getActivityName());
}
}
@@ -1,48 +0,0 @@
package com.cf.imes.module.system.service.funds.recharge;
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsBalanceInfoRespVO;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
import com.cf.imes.module.system.service.pay.PayOrderService;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import java.math.BigDecimal;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Gqr
* @since 2025/10/27 10:44
*/
@Import(RechargeDetailsServiceImpl.class)
class RechargeDetailsServiceImplTest extends BaseDbUnitTest {
@Resource
private RechargeDetailsService detailsService;
@MockitoBean
private PayOrderService payOrderService;
@MockitoBean
private PurchaseService purchaseService;
@Test
void testGetManageRechargeDetailsBalanceInfo() {
// 模拟依赖返回值
when(payOrderService.getRechargeTotalAmount()).thenReturn(new BigDecimal("200.00"));
when(purchaseService.getTotalRechargeUsageAmount()).thenReturn(new BigDecimal("50.00"));
// 调用被测方法
RechargeDetailsBalanceInfoRespVO result = detailsService.getManageRechargeDetailsBalanceInfo();
// 验证逻辑
assertEquals(new BigDecimal("200.00"), result.getRechargeAmount());
assertEquals(new BigDecimal("50.00"), result.getRechargeUsageAmount());
verify(payOrderService).getRechargeTotalAmount();
verify(purchaseService).getTotalRechargeUsageAmount();
}
}
@@ -1,29 +0,0 @@
package com.cf.imes.module.system.validation.manualadjust;
import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest;
import com.cf.imes.module.system.enums.pay.AdjustTypeEnum;
import jakarta.validation.ConstraintValidatorContext;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Gqr
* @since 2025/10/29 9:45
*/
class AdjustTypeValidatorTest extends BaseMockitoUnitTest {
@Mock
private ConstraintValidatorContext constraintValidatorContext;
@Test
void testValid() {
AdjustTypeValidator validator = new AdjustTypeValidator();
assertTrue(validator.isValid(AdjustTypeEnum.INCREASE.getType(), constraintValidatorContext));
assertTrue(validator.isValid(AdjustTypeEnum.DECREASE.getType(), constraintValidatorContext));
assertTrue(validator.isValid(null, constraintValidatorContext));
assertFalse(validator.isValid(100, constraintValidatorContext));
}
}