mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-12 21:02:08 +08:00
1、新增手工调账管理;2、组织新增/修改移除套餐必填;3、组织账户明细支持查询手动调账记录;
This commit is contained in:
+6
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -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, "调减账户赠送金余额不足,请确保组织赠送金余额充足后重新操作");
|
||||
}
|
||||
|
||||
+45
@@ -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));
|
||||
}
|
||||
}
|
||||
+36
@@ -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;
|
||||
}
|
||||
+40
@@ -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;
|
||||
}
|
||||
+45
@@ -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;
|
||||
}
|
||||
+1
-2
@@ -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)
|
||||
|
||||
+4
-2
@@ -115,8 +115,10 @@ public class IncomeExpenseDetailsDO extends BaseDO {
|
||||
*/
|
||||
private String currencyUnit;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
|
||||
+33
-4
@@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+55
@@ -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;
|
||||
}
|
||||
}
|
||||
+20
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-1
@@ -21,7 +21,12 @@ public enum PayChannelCodeEnum {
|
||||
/**
|
||||
* 微信
|
||||
*/
|
||||
WECHAT_NATIVE(1);
|
||||
WECHAT_NATIVE(1),
|
||||
|
||||
/**
|
||||
* 手工调账
|
||||
*/
|
||||
MANUAL_ADJUST(2);
|
||||
|
||||
@EnumValue
|
||||
private final Integer code;
|
||||
|
||||
+15
-1
@@ -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};
|
||||
}
|
||||
}
|
||||
|
||||
-4
@@ -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) {
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ public interface IncomeExpenseService {
|
||||
*
|
||||
* @param incomeExpenseDetailsDO
|
||||
*/
|
||||
void createDetail(IncomeExpenseDetailsDO incomeExpenseDetailsDO);
|
||||
Long createDetail(IncomeExpenseDetailsDO incomeExpenseDetailsDO);
|
||||
|
||||
/**
|
||||
* 查询余额明细分页
|
||||
|
||||
+6
-1
@@ -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());
|
||||
|
||||
+3
@@ -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());
|
||||
|
||||
+30
@@ -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);
|
||||
}
|
||||
+225
@@ -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());
|
||||
}
|
||||
}
|
||||
+2
-6
@@ -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);
|
||||
|
||||
+32
@@ -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 {};
|
||||
}
|
||||
+34
@@ -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;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user