1、新增手工调账管理;2、组织新增/修改移除套餐必填;3、组织账户明细支持查询手动调账记录;

This commit is contained in:
gaoqr
2025-09-16 16:20:54 +08:00
parent 8fdb40a481
commit 0bbb0c9c60
23 changed files with 645 additions and 23 deletions
@@ -77,4 +77,10 @@ public class AssertUtils {
throw exception(errorCode);
}
}
public static void equals(Object obj1, Object obj2, ErrorCode errorCode) {
if (ObjectUtil.equal(obj1, obj2)) {
throw exception(errorCode);
}
}
}
@@ -487,4 +487,9 @@ public class ErrorCodeConstants {
//=========== 产品延期管理 1-002-049-000 ============
public static final ErrorCode PRODUCT_PURCHASE_NO_EXIST = new ErrorCode(1_002_049_001, "当前购买记录不存在,请检查");
//=========== 手工调账管理 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, "调减账户赠送金余额不足,请确保组织赠送金余额充足后重新操作");
}
@@ -0,0 +1,45 @@
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));
}
}
@@ -0,0 +1,36 @@
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 java.time.LocalDateTime;
/**
* @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 = "交易时间")
private LocalDateTime[] createTime;
}
@@ -0,0 +1,40 @@
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;
}
@@ -0,0 +1,45 @@
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;
}
@@ -42,8 +42,7 @@ public class OrganSaveReqVO {
@Size(max = 255, message = "绑定域名长度不能超过255个字符")
private String website;
@Schema(description = "组织套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "组织套餐编号不能为空")
@Schema(description = "组织套餐编号", example = "1024")
private Long packageId;
@Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
@@ -115,8 +115,10 @@ public class IncomeExpenseDetailsDO extends BaseDO {
*/
private String currencyUnit;
/**
* 备注
*/
private String remark;
}
@@ -1,11 +1,15 @@
package com.cf.imes.module.system.dal.mysql.incomeandexpense;
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.balancedetails.vo.BalanceDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
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;
/**
@@ -23,13 +27,38 @@ public interface IncomeExpenseDetailsMapper extends BaseMapperX<IncomeExpenseDet
* @return
*/
default PageResult<IncomeExpenseDetailsDO> selectDetailsPage(BalanceDetailsPageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<IncomeExpenseDetailsDO>()
LambdaQueryWrapperX<IncomeExpenseDetailsDO> queryWrapperX = new LambdaQueryWrapperX<IncomeExpenseDetailsDO>()
.eqIfPresent(IncomeExpenseDetailsDO::getOrganId, pageReqVO.getOrganId())
.eq(IncomeExpenseDetailsDO::getDeleted, false)
.likeIfPresent(IncomeExpenseDetailsDO::getBusinessNo, pageReqVO.getBusinessNo())
.eqIfPresent(IncomeExpenseDetailsDO::getTradeType,pageReqVO.getTradeType())
.betweenIfPresent(IncomeExpenseDetailsDO::getCreateTime,pageReqVO.getCreateTime())
.orderByDesc(IncomeExpenseDetailsDO::getId));
.betweenIfPresent(IncomeExpenseDetailsDO::getCreateTime, pageReqVO.getCreateTime())
.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 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)
);
}
}
@@ -0,0 +1,55 @@
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,4 +49,24 @@ 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;
}
}
@@ -21,7 +21,12 @@ public enum PayChannelCodeEnum {
/**
* 微信
*/
WECHAT_NATIVE(1);
WECHAT_NATIVE(1),
/**
* 手工调账
*/
MANUAL_ADJUST(2);
@EnumValue
private final Integer code;
@@ -21,7 +21,12 @@ public enum TradeTypeEnum implements BaseEnum {
/**
* 产品购买
*/
PRODUCT(1, "产品购买");
PRODUCT(1, "产品购买"),
/**
* 手工调账
*/
MANUAL_ADJUST(2, "手工调账");
private final Integer code;
@@ -55,4 +60,13 @@ public enum TradeTypeEnum implements BaseEnum {
public static boolean isProduct(Integer code) {
return PRODUCT.getCode().equals(code);
}
/**
* 获取需要筛选的类型:充值、产品购买
*
* @return
*/
public static TradeTypeEnum[] validArr() {
return new TradeTypeEnum[]{RECHARGE, PRODUCT};
}
}
@@ -6,7 +6,6 @@ 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.object.BeanUtils;
import com.cf.imes.module.system.controller.admin.funds.delay.ProductDelayController;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelaySaveReqVO;
@@ -19,7 +18,6 @@ import com.cf.imes.module.system.service.funds.products.ProductsDetailService;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
import com.cf.imes.module.system.service.organ.OrganService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
@@ -46,8 +44,6 @@ public class ProductDelayServiceImpl implements ProductDelayService {
@Resource
private ProductDelayRecordMapper productDelayRecordMapper;
@Autowired
private ProductDelayController productDelayController;
@Override
public Long createProductDelay(ProductDelaySaveReqVO productDelaySaveReqVO) {
@@ -17,7 +17,7 @@ public interface IncomeExpenseService {
*
* @param incomeExpenseDetailsDO
*/
void createDetail(IncomeExpenseDetailsDO incomeExpenseDetailsDO);
Long createDetail(IncomeExpenseDetailsDO incomeExpenseDetailsDO);
/**
* 查询余额明细分页
@@ -36,8 +36,9 @@ public class IncomeExpenseServiceImpl implements IncomeExpenseService {
private OrganService organService;
@Override
public void createDetail(IncomeExpenseDetailsDO incomeExpenseDetailsDO) {
public Long createDetail(IncomeExpenseDetailsDO incomeExpenseDetailsDO) {
incomeExpenseDetailsMapper.insert(incomeExpenseDetailsDO);
return incomeExpenseDetailsDO.getId();
}
@Override
@@ -72,6 +73,10 @@ public class IncomeExpenseServiceImpl implements IncomeExpenseService {
respVO.setRechargePayAmount(record.getAlipaySpent().add(record.getWechatSpent()));
respVO.setGiftPayAmount(record.getGiftMoneySpent());
}
} else if (TradeTypeEnum.MANUAL_ADJUST.getCode().equals(tradeType)) {
respVO.setRechargeAmount(i.getCashAmountChange());
// 手工调账算到充值
respVO.setTradeType(TradeTypeEnum.RECHARGE.getCode());
}
// 查询操作组织名
OrganizationDO organ = organService.getOrgan(i.getOrganId());
@@ -41,6 +41,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@@ -196,6 +197,7 @@ public class InvoiceServiceImpl implements InvoiceService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public void applyInvoice(InvoiceRecordsReqVO reqVO) {
Long organId = SecurityFrameworkUtils.getUserOrganId();
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
@@ -292,6 +294,7 @@ public class InvoiceServiceImpl implements InvoiceService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public void confirmInvoice(InvoiceConfirmReqVO reqVO, MultipartFile file) throws IOException {
// 校验发票申请记录是否存在
InvoiceRecordsDO invoiceRecordsDO = validateInvoiceExists(reqVO.getId());
@@ -0,0 +1,30 @@
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);
}
@@ -0,0 +1,225 @@
package com.cf.imes.module.system.service.funds.manualadjust;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
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.LambdaUpdateWrapperX;
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.dal.mysql.funds.organamount.OrganAmountMapper;
import com.cf.imes.module.system.dal.mysql.incomeandexpense.IncomeExpenseDetailsMapper;
import com.cf.imes.module.system.dal.mysql.pay.PayOrderMapper;
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.PayConstants;
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 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.ORGAN_RECHARGE_AMOUNT_UPDATE_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 OrganAmountMapper organAmountMapper;
@Resource
private IncomeExpenseService incomeExpenseService;
@Resource
private MybatisIdProperties mybatisIdProperties;
@Resource
private PayOrderMapper payOrderMapper;
@Resource
private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper;
@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 = null;
switch (AdjustTypeEnum.getByType(saveReqVO.getAdjustType())) {
case INCREASE:
// 调增直接累加
rechargeRespVO = recharge(organAmountDO, 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 = recharge(organAmountDO, rechargeAmount, giftAmount);
break;
default:
break;
}
// 新增支付单
PayOrderDO payOrderDO = createPayOrder(organId, rechargeAmount);
payOrderMapper.insert(payOrderDO);
// 新增收支明细
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.orderNo(payOrderDO.getPayNo())
.businessNo(LocalDateTimeUtils.formatNow())
.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.setPayNo(String.format(PayConstants.PAY_ORDER_PREFIX_FORMAT, organId, payOrderId));
payOrderDO.setStatus(PayOrderStatusEnum.SUCCESS);
payOrderDO.setPrice(recharge);
payOrderDO.setSubject("手工调账");
payOrderDO.setChannelCode(PayChannelCodeEnum.MANUAL_ADJUST);
payOrderDO.setOrganId(organId);
return payOrderDO;
}
/**
* 充值
*
* @param organAmountDO
* @param price
* @param gift
*/
private OrganRechargeAmountRespVO recharge(OrganAmountDO organAmountDO, BigDecimal price, BigDecimal gift) {
Long organId = organAmountDO.getOrganId();
BigDecimal newAmount = organAmountDO.getAmount().add(price);
BigDecimal newGift = null;
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())
.setIfPresent(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())
.setIfPresent(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(ObjectUtil.isNull(newGift) ? newAmount : newAmount.add(newGift), newAmount, newGift);
}
} else {
return new OrganRechargeAmountRespVO(ObjectUtil.isNull(newGift) ? newAmount : newAmount.add(newGift), newAmount, newGift);
}
}
@Override
public PageResult<ManualAdjustAccountBalanceRespVO> getPage(ManualAdjustAccountBalancePageReqVO pageReqVO) {
PageResult<IncomeExpenseDetailsDO> incomeExpenseDetailsDOPageResult = incomeExpenseDetailsMapper.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.getOrgan(detailsDO.getOrganId());
if (ObjectUtil.isNotNull(organ)) {
respVO.setOrganName(organ.getName());
}
resultList.add(respVO);
}
return new PageResult<>(resultList, incomeExpenseDetailsDOPageResult.getTotal());
}
}
@@ -279,8 +279,7 @@ public class OrganServiceImpl implements OrganService {
validTenantWebsiteDuplicate(updateReqVO.getWebsite(), organId);
// 校验组织手机号是否重复
validContactMobileDuplicate(updateReqVO.getOrgAdminMobile(),organId);
// 校验套餐被禁用
TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(updateReqVO.getPackageId());
if(!Objects.equals(tenant.getName(), updateReqVO.getName())) {
String pinyinFull = PinYinUtils.convertToPinyin(tenant.getName());
if(CharSequenceUtil.isNotBlank(pinyinFull)) {
@@ -307,10 +306,7 @@ public class OrganServiceImpl implements OrganService {
// 更新组织
OrganizationDO updateObj = BeanUtils.toBean(updateReqVO, OrganizationDO.class);
organMapper.updateById(updateObj);
// 如果套餐发生变化,则修改其角色的权限
if (ObjectUtil.notEqual(tenant.getPackageId(), updateReqVO.getPackageId())) {
permissionService.flushCacheWhenTenantPackageChange(List.of(tenant.getId()));
}
if (CommonStatusEnum.DISABLE.getStatus().equals(updateReqVO.getStatus())) {
// 移除机构下用户的token
scanAndCompareDeptAndDelToken(String.format(OAUTH2_ACCESS_TOKEN, "*"), organId);
@@ -0,0 +1,32 @@
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 {};
}
@@ -0,0 +1,34 @@
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;
}
}
@@ -17,7 +17,7 @@ public class TradeTypeEnumValidator implements ConstraintValidator<TradeTypeEnum
if (ObjectUtil.isNull(value)) {
return true;
}
for (TradeTypeEnum codeEnum : TradeTypeEnum.values()) {
for (TradeTypeEnum codeEnum : TradeTypeEnum.validArr()) {
if (ObjectUtil.equal(codeEnum.getCode(), value)) {
return true;
}