1、组织创建新增产品购买记录;2、新增管理端销售管理、充值管理接口;3、新增修正双端账户明细;4、修正资金总览、账户总览信息接口数据;

This commit is contained in:
gaoqr
2025-09-12 18:23:44 +08:00
parent f47e915f54
commit 4cd5869b81
54 changed files with 1210 additions and 439 deletions
@@ -139,6 +139,7 @@ public class ErrorCodeConstants {
public static final ErrorCode ORGAN_ALREADY_EXISTS = new ErrorCode(1_002_015_007, "该新增组织已授权机台数量无需重复新增!");
public static final ErrorCode ORGAN_USER_OPER_NOT_ALLOW = new ErrorCode(1_002_015_008, "不允许操作用户自身组织");
public static final ErrorCode ORGAN_CONTACTMOBILE_DUPLICATE = new ErrorCode(1_002_015_009, "手机号为【{}】的组织已存在");
public static final ErrorCode ORGAN_CREATE_PRODUCTLIST_EMPTY_ERROR = new ErrorCode(1_002_015_010, "组织创建购买产品列表不能为空");
// ========== 组织套餐 1-002-016-000 ==========
public static final ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "组织套餐不存在");
@@ -1,6 +1,5 @@
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;
@@ -41,16 +40,13 @@ public class BalanceDetailsController {
private IncomeExpenseService incomeExpenseService;
@GetMapping("")
@Operation(summary = "查询组织余额明细分页")
@Operation(summary = "查询组织账户明细分页")
public CommonResult<PageResult<BalanceDetailsRespVO>> getBalanceDetailsPage(@Valid BalanceDetailsPageReqVO pageReqVO) {
return success(incomeExpenseService.getBalanceDetailsPage(pageReqVO));
}
@GetMapping("/export")
@Operation(summary = "组织余额明细导出")
@Operation(summary = "组织账户明细导出")
@OperateLog(type = EXPORT)
public void balanceDetailsExport(@Valid BalanceDetailsPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
@@ -2,9 +2,9 @@ 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.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -15,7 +15,7 @@ import java.time.LocalDate;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
@Schema(description = "管理后台 - 组织余额明细分页 Request VO")
@Schema(description = "管理后台 - 组织账户明细分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@@ -23,16 +23,13 @@ public class BalanceDetailsPageReqVO extends PageParam {
@Schema(description = "流水号")
@Size(max = 64, message = "流水号长度不能超过64个字符")
private String businessNo;
@Schema(description = "交易类型")
@TradeTypeEnumValid
private Integer tradeType;
@Schema(description = "收支类型")
@IncomeExpenseTypeEnumValid
private Integer incomeExpenseType;
@Schema(description = "创建时间", example = "[2022-07-01 ,2022-07-01]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate[] createTime;
@@ -40,5 +37,7 @@ public class BalanceDetailsPageReqVO extends PageParam {
@Schema(description = "组织ID")
private Long organId;
@Schema(description = "操作人")
@Size(max = 64, message = "操作人长度不能超过64个字符")
private String operator;
}
@@ -1,6 +1,5 @@
package com.cf.imes.module.system.controller.admin.funds.balancedetails.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;
@@ -15,78 +14,53 @@ import java.time.LocalDateTime;
@Data
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 entryAmount;
@Schema(description = "产品金额")
@ExcelProperty("产品金额")
private BigDecimal productPrice;
@Schema(description = "现金支付")
@ExcelProperty("现金支付")
private BigDecimal balancePayAmount;
@Schema(description = "入账赠送金")
@ExcelProperty("入账赠送金")
private BigDecimal entryGiftAmount;
@Schema(description = "支出现金")
@ExcelProperty("支出现金")
private BigDecimal expensesAmount;
@Schema(description = "支出赠送金")
@ExcelProperty("支出赠送金")
private BigDecimal expensesGiftAmount;
@Schema(description = "可用金额")
@ExcelProperty("可用金额")
private BigDecimal availableAmount;
@Schema(description = "现金金额")
@ExcelProperty("现金金额")
private BigDecimal amount;
@Schema(description = "赠送金额")
@ExcelProperty("赠送金额")
private BigDecimal giftAmount;
@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 = "支出/入账现金金额")
@ExcelIgnore
private BigDecimal cashAmountChange;
@Schema(description = "支出/入账赠送金金额")
@ExcelIgnore
private BigDecimal giftAmountChange;
}
@@ -1,36 +1,29 @@
package com.cf.imes.module.system.controller.admin.funds.organamount;
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.module.system.controller.admin.funds.organamount.vo.AllOrganAmountRespVO;
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.TotalAmountDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalAmountDetailsRespVO;
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 jakarta.servlet.http.HttpServletResponse;
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;
import jakarta.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
/**
* @author 组织资金
@@ -52,30 +45,25 @@ public class OrganAmountController {
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<AllOrganAmountRespVO> getManageTotalAmount() {
@Operation(summary = "获取管理端金总")
public CommonResult<ManageAmountOverviewRespVO> getManageTotalAmount() {
return success(organAmountService.getOrganAmountAll());
}
@GetMapping("/manage/total/details")
@Operation(summary = "获取管理端总额明细")
public CommonResult<PageResult<TotalAmountDetailsRespVO>> getManageTotalAmountDetails(@Valid TotalAmountDetailsPageReqVO reqVO) {
return success(organAmountService.getManageTotalAmountDetails(reqVO));
}
@GetMapping("/manage/total/details/export")
@Operation(summary = "管理端总额明细导出")
@OperateLog(type = EXPORT)
public void exportManageTotalAmountDetails(@Valid TotalAmountDetailsPageReqVO reqVO,
HttpServletResponse response) throws IOException {
reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<TotalAmountDetailsRespVO> list = organAmountService.getManageTotalAmountDetails(reqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "总额明细.xls", "数据", TotalAmountDetailsRespVO.class,
BeanUtils.toBean(list, TotalAmountDetailsRespVO.class));
}
@GetMapping("/statistics/consumptionTrend")
@Operation(summary = "获取组织消费趋势")
public CommonResult<Map<String, Object>> getOrganConsumptionTrend(@Valid OrganFundsStatisticsReqVO reqVO) {
@@ -1,22 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.organamount.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 所有组织的余额信息 Response VO")
@Data
public class AllOrganAmountRespVO {
@Schema(description = "所有组织的余额")
private BigDecimal allOrganAmount;
@Schema(description = "待审核的发票金额")
private BigDecimal toExamineAmount;
}
@@ -0,0 +1,24 @@
package com.cf.imes.module.system.controller.admin.funds.organamount.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 管理端资金总览 Response VO")
@Data
public class ManageAmountOverviewRespVO {
@Schema(description = "销售总额现充支付")
private BigDecimal totalSalesAmount;
@Schema(description = "销售总额赠送金支付")
private BigDecimal totalSalesGiftAmount;
@Schema(description = "充值余额")
private BigDecimal rechargeBalance;
@Schema(description = "待审核的发票金额")
private BigDecimal toExamineAmount;
}
@@ -0,0 +1,21 @@
package com.cf.imes.module.system.controller.admin.funds.organamount.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author Gqr
* @since 2025/9/11 15:48
*/
@Schema(description = "管理后台 - 可用金额 Response VO")
@Data
public class OrganAvailableAmountRespVO {
@Schema(description = "现金余额")
private BigDecimal amount;
@Schema(description = "赠送金余额")
private BigDecimal giftAmount;
}
@@ -1,32 +0,0 @@
package com.cf.imes.module.system.controller.admin.funds.organamount.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 lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDate;
/**
* @author Gqr
* @since 2025/9/2 14:14
*/
@Schema(description = "管理后台 - 总额明细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TotalAmountDetailsPageReqVO extends PageParam {
@Schema(description = "时间范围")
private LocalDate[] createTime;
@Schema(description = "交易类型")
@TradeTypeEnumValid
private Integer tradeType;
@Schema(description = "收入支出类型")
@IncomeExpenseTypeEnumValid
private Integer incomeExpenseType;
}
@@ -6,24 +6,21 @@ import lombok.Data;
import java.math.BigDecimal;
/**
* 销售总额明细充值赠送
*
* @author Gqr
* @since 2025/8/14 15:20
*/
@Data
@AllArgsConstructor
public class OrganPayAmountRespVO {
public class TotalSalesAmountRespVO {
/**
* 可用余
*/
private BigDecimal availableAmount;
/**
* 现金余额
* 现充支付总
*/
private BigDecimal amount;
/**
* 赠送金
* 赠送金支付总
*/
private BigDecimal giftAmount;
}
@@ -27,7 +27,7 @@ public class ProductDetailsRespVO {
@Schema(description = "购买时长", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String duration;
@Schema(description = "产品时长单位,0:年、1:月、2:日", example = "1")
@Schema(description = "产品时长单位,0:年、1:月", example = "1")
private Integer durationUnit;
@Schema(description = "正常产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
@@ -36,7 +36,7 @@ public class ProductDetailsRespVO {
@Schema(description = "赠送时长", example = "1")
private Integer giftDuration;
@Schema(description = "赠送时长单位,0:年、1:月、2:日", example = "1")
@Schema(description = "赠送时长单位,0:年、1:月", example = "1")
private Integer giftDurationUnit;
@Schema(description = "赠送产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
@@ -30,17 +30,17 @@ public class ProductDetailsSaveReqVO {
@Schema(description = "产品时间,格式:时长值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String duration;
@Schema(description = "产品时长单位,0:年、1:月、2:日", example = "1")
@Schema(description = "产品时长单位,0:年、1:月", example = "1")
@TimeUnitValid
private Integer durationUnit;
@Schema(description = "产品产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
private BigDecimal output;
//
@Schema(description = "赠送时间,格式:时长值 - 时间单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String giftDuration;
@Schema(description = "赠送时长单位,0:年、1:月、2:日", example = "1")
@Schema(description = "赠送时长单位,0:年、1:月", example = "1")
@TimeUnitValid
private Integer giftDurationUnit;
@@ -1,6 +1,5 @@
package com.cf.imes.module.system.controller.admin.funds.purchase;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
@@ -34,7 +33,6 @@ import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT
@Validated
public class PurchaseController {
@Resource
private PurchaseService purchaseService;
@@ -47,23 +45,14 @@ public class PurchaseController {
}
@GetMapping("/export")
@Operation(summary = "导出软件购买记录")
@OperateLog(type = EXPORT)
public void billDetailsExport(@Valid PurchaseRecordPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<PurchaseRecordRespVO> list = purchaseService.getPurchaseRecord(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "软件购买记录表.xls", "数据", PurchaseRecordRespVO.class, list);
}
}
@@ -0,0 +1,62 @@
package com.cf.imes.module.system.controller.admin.funds.purchase;
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.excel.core.util.ExcelUtils;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailsPageReqVO;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
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/sales")
@Validated
public class SalesDetailsController {
@Resource
private PurchaseService purchaseService;
@GetMapping("/page")
@Operation(summary = "获取销售明细分页")
public CommonResult<PageResult<SalesDetailRespVO>> getManageSalesDetailsPage(@Valid SalesDetailsPageReqVO pageReqVO) {
return success(purchaseService.getManageSalesDetailsPage(pageReqVO));
}
@GetMapping("/export")
@Operation(summary = "导出充值明细")
@OperateLog(type = EXPORT)
public void exportSalesDetailsPage(@Valid SalesDetailsPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<SalesDetailRespVO> list = purchaseService.getManageSalesDetailsPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "销售明细表.xls", "数据", SalesDetailRespVO.class, list);
}
@GetMapping("/total")
@Operation(summary = "获取管理端销售总额信息")
public CommonResult<TotalSalesAmountRespVO> getManageRechargeDetailsBalanceInfo() {
return success(purchaseService.getTotalSales());
}
}
@@ -13,6 +13,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@@ -49,7 +50,7 @@ public class PurchaseRecordRespVO {
@ExcelProperty("购买时长")
private Integer purchaseDuration;
@Schema(description = "购买时长单位,0:年、1:月、2:日", example = "1")
@Schema(description = "购买时长单位,0:年、1:月", example = "1")
@ExcelProperty(value = "购买时长单位", converter = EnumConvert.class)
@EnumFormat(value = DurationUnitEnum.class)
private Integer purchaseDurationUnit;
@@ -58,7 +59,7 @@ public class PurchaseRecordRespVO {
@ExcelProperty("赠送时长")
private Integer giftDuration;
@Schema(description = "赠送时长单位,0:年、1:月、2:日", example = "1")
@Schema(description = "赠送时长单位,0:年、1:月", example = "1")
@ExcelProperty(value = "赠送时长单位", converter = EnumConvert.class)
@EnumFormat(value = DurationUnitEnum.class)
private Integer giftDurationUnit;
@@ -104,7 +105,7 @@ public class PurchaseRecordRespVO {
@Schema(description = "失效时间")
@ExcelProperty("失效时间")
private LocalDateTime endTime;
private LocalDate endTime;
@Schema(description = "操作人")
@ExcelProperty("操作人")
@@ -0,0 +1,57 @@
package com.cf.imes.module.system.controller.admin.funds.purchase.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.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 SalesDetailRespVO {
@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 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;
}
@@ -0,0 +1,44 @@
package com.cf.imes.module.system.controller.admin.funds.purchase.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 SalesDetailsPageReqVO 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;
}
@@ -0,0 +1,63 @@
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.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.excel.core.util.ExcelUtils;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailRespVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsBalanceInfoRespVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsPageReqVO;
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 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 Gqr
* @since 2025/9/11 16:18
*/
@Tag(name = "管理后台 - 充值明细管理")
@RestController
@RequestMapping("/system/rechargeDetails")
@Validated
public class RechargeDetailsController {
@Resource
private RechargeDetailsService rechargeDetailsService;
@GetMapping("/page")
@Operation(summary = "获取充值明细分页")
public CommonResult<PageResult<RechargeDetailRespVO>> getRechargeDetailsPage(@Valid RechargeDetailsPageReqVO pageReqVO) {
return success(rechargeDetailsService.getRechargeDetailsPage(pageReqVO));
}
@GetMapping("/export")
@Operation(summary = "导出充值明细")
@OperateLog(type = EXPORT)
public void exportRechargeDetails(@Valid RechargeDetailsPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<RechargeDetailRespVO> list = rechargeDetailsService.getRechargeDetailsPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "充值明细表.xls", "数据", RechargeDetailRespVO.class, list);
}
@GetMapping("/balance")
@Operation(summary = "获取管理端充值明细余额信息")
public CommonResult<RechargeDetailsBalanceInfoRespVO> getManageRechargeDetailsBalanceInfo() {
return success(rechargeDetailsService.getManageRechargeDetailsBalanceInfo());
}
}
@@ -1,9 +1,9 @@
package com.cf.imes.module.system.controller.admin.funds.organamount.vo;
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.IncomeExpenseTypeEnum;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -13,52 +13,57 @@ import java.time.LocalDateTime;
/**
* @author Gqr
* @since 2025/9/2 14:51
* @since 2025/9/11 18:26
*/
@Schema(description = "管理后台 - 总额明细信息 Response VO")
@Schema(description = "管理后台 - 充值明细 Resp VO")
@Data
public class TotalAmountDetailsRespVO {
public class RechargeDetailRespVO {
@Schema(description = "流水号")
@ExcelProperty("流水号")
private String businessNo;
private Long id;
@Schema(description = "交易类型,0充值 1软件购买")
@ExcelProperty(value = "交易类型", converter = EnumConvert.class)
@EnumFormat(value = TradeTypeEnum.class)
private Integer tradeType;
@Schema(description = "收支类型,0收入 1支出")
@ExcelProperty(value = "收支类型", converter = EnumConvert.class)
@EnumFormat(value = IncomeExpenseTypeEnum.class)
private Integer incomeExpenseType;
@Schema(description = "订单号")
@ExcelProperty("订单号")
private String payNo;
@Schema(description = "充值金额")
@ExcelProperty("充值金额")
private BigDecimal rechargeAmount;
private BigDecimal price;
@ExcelIgnore
private Long purchaseId;
@Schema(description = "产品金额")
@ExcelProperty("产品金额")
private BigDecimal productAmount;
private BigDecimal totalAmount;
@Schema(description = "现金金额支付")
@ExcelProperty("现金金额支付")
private BigDecimal cashAmount;
@Schema(description = "账户充值支付")
@ExcelProperty("账户充值支付")
private BigDecimal rechargeSpent;
@Schema(description = "账户现金余额")
@ExcelProperty("账户现金余额")
private BigDecimal accountCashBalance;
@Schema(description = "现金支付")
@ExcelProperty("现金支付")
private BigDecimal accountBalanceSpent;
@Schema(description = "账户赠送金支付")
@ExcelProperty("账户赠送金支付")
private BigDecimal giftMoneySpent;
@Schema(description = "操作人")
@ExcelProperty("操作人")
private String operatorName;
private String creator;
@Schema(description = "操作组织")
@ExcelProperty("操作组织")
@Schema(description = "组织名称")
@ExcelProperty("组织名称")
private String organName;
@Schema(description = "交易时间")
@ExcelProperty("交易时间")
private LocalDateTime createTime;
}
@@ -0,0 +1,21 @@
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;
}
@@ -0,0 +1,44 @@
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;
}
@@ -10,9 +10,11 @@ import com.cf.imes.framework.excel.core.util.ExcelUtils;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.module.system.api.user.dto.OrganAdminUserRespDTO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.*;
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.dataobject.organ.TenantPackageDO;
import com.cf.imes.module.system.dal.mysql.organ.TenantPackageMapper;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
import com.cf.imes.module.system.service.organ.OrganService;
import com.cf.imes.module.system.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.Operation;
@@ -49,6 +51,9 @@ public class OrganController {
@Resource
private AdminUserService adminUserService;
@Resource
private PurchaseService purchaseService;
@GetMapping("/get-id-by-name")
@PermitAll
@Operation(summary = "使用组织名,获得组织编号", description = "登录界面,根据用户的组织名,获得组织编号")
@@ -119,15 +124,16 @@ public class OrganController {
return success(new PageResult<>());
}
PageResult<OrganRespVO> bean = BeanUtils.toBean(pageResult, OrganRespVO.class);
Set<Long> packageIds = bean.getList().stream().map(OrganRespVO::getPackageId).collect(Collectors.toSet());
List<TenantPackageDO> tenantPackageDOS = tenantPackageMapper.selectBatchIds(packageIds);
bean.getList().forEach(e->{
e.setPackageName(tenantPackageDOS.stream()
.filter(f->Objects.equals(f.getId(), e.getPackageId()))
.map(TenantPackageDO::getName)
.findAny()
.orElse("")
);
Set<Long> organIds = bean.getList().stream().map(OrganRespVO::getId).collect(Collectors.toSet());
// 查询当次列表组织下的所有购买记录
List<PurchaseRecordDO> orgPurchaseList = purchaseService.getOrgPurchaseList(organIds);
// 匹配到对应的组织下
bean.getList().forEach(e -> {
e.setOrganPurchaseList(orgPurchaseList.stream()
.filter(f -> Objects.equals(f.getOrganId(), e.getId()))
.map(m -> BeanUtils.toBean(m, OrganPagePurchaseRespVO.class))
.toList());
});
return success(bean);
}
@@ -0,0 +1,30 @@
package com.cf.imes.module.system.controller.admin.organ.vo.organ;
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 lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
@Schema(description = "管理后台 - 组织创建购买产品 Request VO")
@Data
public class OrganCreateProductPurchaseReqVO {
@Schema(description = "定价规则编号",example = "1")
@NotNull(message = "定价规则编号不能为空")
private Long productDetailsId;
@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 = "产品有效时间")
@NotNull(message = "产品有效时间不能为空")
private LocalDate productExpireDate;
}
@@ -0,0 +1,44 @@
package com.cf.imes.module.system.controller.admin.organ.vo.organ;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
/**
* @author Gqr
* @since 2025/9/11 9:52
*/
@Schema(description = "管理后台 - 组织产品购买记录 Request VO")
@Data
public class OrganPagePurchaseRespVO {
@Schema(description = "购买记录编号")
private Long id;
@Schema(description = "产品名称")
private String productName;
@Schema(description = "购买时长", example = "1")
private Integer purchaseDuration;
@Schema(description = "购买时长单位,0:年、1:月", example = "1")
private Integer purchaseDurationUnit;
@Schema(description = "赠送时长", example = "1")
private Integer giftDuration;
@Schema(description = "赠送时长单位,0:年、1:月", example = "1")
private Integer giftDurationUnit;
@Schema(description = "订单总额")
private BigDecimal totalAmount;
@Schema(description = "失效时间")
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate endTime;
}
@@ -1,5 +1,6 @@
package com.cf.imes.module.system.controller.admin.organ.vo.organ;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.cf.imes.framework.excel.core.annotations.DictFormat;
import com.cf.imes.framework.excel.core.convert.DictConvert;
import com.cf.imes.module.system.enums.DictTypeConstants;
@@ -9,6 +10,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 组织 Response VO")
@Data
@@ -89,4 +91,7 @@ public class OrganRespVO {
@ExcelProperty("纬度")
private String latitude;
@Schema(description = "产品购买记录")
@ExcelIgnore
private List<OrganPagePurchaseRespVO> organPurchaseList;
}
@@ -8,6 +8,7 @@ import lombok.Data;
import jakarta.validation.constraints.*;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 组织创建/修改 Request VO")
@Data
@@ -21,16 +22,16 @@ public class OrganSaveReqVO {
@Size(min = 1, max = 30, message = "组织名长度不能超过30个字符")
private String name;
@Schema(description = "联系人", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰")
@Schema(description = "管理员姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰")
@NotNull(message = "联系人不能为空")
@Size(min = 1, max = 30, message = "联系人长度不能超过30个字符")
private String contactName;
private String orgAdminName;
@Schema(description = "联系手机", example = "15601691300")
@Schema(description = "管理员账号", example = "15601691300")
@Mobile
@NotNull(message = "联系人手机不能为空")
@Size(max = 11, message = "联系人手机长度不能超过11个字符")
private String contactMobile;
@NotNull(message = "管理员账号不能为空")
@Size(max = 11, message = "管理员账号(手机号)长度不能超过11个字符")
private String orgAdminMobile;
@Schema(description = "组织状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "组织状态")
@@ -110,4 +111,8 @@ public class OrganSaveReqVO {
@Schema(description = "是否开启灰度,0:开启、1:关闭", example = "0")
@CommonStatus
private Integer grayStatus;
@Schema(description = "产品购买列表")
@Size(max = 10, message = "创建组织时最少可购买1个产品,最多可购买10个产品")
private List<OrganCreateProductPurchaseReqVO> productPurchaseReqVOS;
}
@@ -17,8 +17,8 @@ public interface OrganConvert {
default UserSaveReqVO convert02(OrganSaveReqVO bean) {
UserSaveReqVO reqVO = new UserSaveReqVO();
reqVO.setMobile(bean.getContactMobile());
reqVO.setNickname(bean.getContactName());
reqVO.setMobile(bean.getOrgAdminMobile());
reqVO.setNickname(bean.getOrgAdminName());
return reqVO;
}
@@ -13,7 +13,7 @@ import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDate;
/**
@@ -85,13 +85,13 @@ public class PurchaseRecordDO extends BaseDO {
/**
* 产品开始时间
*/
private LocalDateTime startTime;
private LocalDate startTime;
/**
* 产品结束时间
*/
private LocalDateTime endTime;
private LocalDate endTime;
/**
@@ -38,6 +38,10 @@ public class IncomeExpenseDetailsDO extends BaseDO {
*/
private String businessNo;
/**
* 订单号
*/
private String orderNo;
/**
* 组织ID
@@ -58,6 +58,11 @@ public class PayOrderDO extends BaseDO {
*/
private Long rechargeActivityId;
/**
* 购买记录id
*/
private Long purchaseId;
/**
* 支付订单号:P + 当前id + 时间戳(yyyyMMddHHmmss
*/
@@ -0,0 +1,65 @@
package com.cf.imes.module.system.dal.dataobject.pay;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 充值明细实体
*
* @author Gqr
* @since 2025/9/11 18:26
*/
@Data
public class PayOrderRechargeDetailDO {
/**
* 主键
*/
private Long id;
/**
* 组织id
*/
private Long organId;
/**
* 支付订单号
*/
private String payNo;
/**
* 支付价格
*/
private BigDecimal price;
/**
* 购买记录id
*/
private Long purchaseId;
/**
* 购买总额
*/
private BigDecimal totalAmount;
/**
* 现金余额支出
*/
private BigDecimal accountBalanceSpent;
/**
* 赠送金支出
*/
private BigDecimal giftMoneySpent;
/**
* 操作人
*/
private String creator;
/**
* 交易时间
*/
private LocalDateTime createTime;
}
@@ -2,11 +2,13 @@ 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
@@ -19,4 +21,19 @@ public interface OrganAmountMapper extends BaseMapperX<OrganAmountDO> {
* @return
*/
List<OrganAmountGroupByCreateTimeRespVO> selectOrganIncomeExpenseTrendGroupByCreateTime(@Param("req") OrganFundsStatisticsReqVO reqVO, @Param("organId") Long organId);
/**
* 查询充值余额总额
*
* @return
*/
BigDecimal getTotalRechargeAmount();
/**
* 查询所有组织的可用金
*
* @return
*/
OrganAvailableAmountRespVO getTotalAvailableAmount();
}
@@ -7,7 +7,9 @@ import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailsPageReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import com.cf.imes.module.system.enums.pay.InvoiceStatusEnum;
import org.apache.ibatis.annotations.Mapper;
@@ -68,6 +70,7 @@ public interface PurchaseRecordMapper extends BaseMapperX<PurchaseRecordDO> {
/**
* 查询机构下开票金额统计:可开票、开票中、已开票
*
* @param organId
* @return
*/
@@ -79,4 +82,36 @@ public interface PurchaseRecordMapper extends BaseMapperX<PurchaseRecordDO> {
* @param organId
*/
BigDecimal getInvoicableAmount(Long organId, @Param("ids") List<Long> ids);
/**
* 查询销售总额
*
* @return
*/
TotalSalesAmountRespVO getTotalSales();
/**
* 查询购买记录中的现金使用金额总数
*
* @return
*/
BigDecimal getTotalRechargeUsageAmount();
/**
* 分页查询销售记录
*
* @return
*/
default PageResult<PurchaseRecordDO> getSaleDetailsPage(SalesDetailsPageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<PurchaseRecordDO>()
.betweenIfPresent(PurchaseRecordDO::getCreateTime, pageReqVO.getCreateTime())
.eqIfPresent(PurchaseRecordDO::getTotalAmount, pageReqVO.getProductPrice())
.eqIfPresent(PurchaseRecordDO::getOrganId, pageReqVO.getOrganId())
.eqIfPresent(PurchaseRecordDO::getCreator, pageReqVO.getOperator())
.eq(PurchaseRecordDO::getDeleted, false)
.orderByDesc(PurchaseRecordDO::getCreateTime)
.select(PurchaseRecordDO::getId, PurchaseRecordDO::getOrganId, PurchaseRecordDO::getTotalAmount, PurchaseRecordDO::getAccountBalanceSpent, PurchaseRecordDO::getAlipaySpent,
PurchaseRecordDO::getWechatSpent, PurchaseRecordDO::getGiftMoneySpent, PurchaseRecordDO::getCreator, PurchaseRecordDO::getCreateTime)
);
}
}
@@ -1,13 +1,10 @@
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.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.organamount.vo.TotalAmountDetailsPageReqVO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
import org.apache.ibatis.annotations.Mapper;
@@ -26,29 +23,13 @@ public interface IncomeExpenseDetailsMapper extends BaseMapperX<IncomeExpenseDet
* @return
*/
default PageResult<IncomeExpenseDetailsDO> selectDetailsPage(BalanceDetailsPageReqVO pageReqVO) {
Long organId = pageReqVO.getOrganId();
return selectPage(pageReqVO, new LambdaQueryWrapperX<IncomeExpenseDetailsDO>()
.eqIfPresent(IncomeExpenseDetailsDO::getOrganId, ObjectUtil.isNotNull(organId) ? organId : SecurityFrameworkUtils.getUserOrganId())
.eqIfPresent(IncomeExpenseDetailsDO::getOrganId, pageReqVO.getOrganId())
.eq(IncomeExpenseDetailsDO::getDeleted, false)
.likeIfPresent(IncomeExpenseDetailsDO::getBusinessNo, pageReqVO.getBusinessNo())
.eqIfPresent(IncomeExpenseDetailsDO::getTradeType,pageReqVO.getTradeType())
.eqIfPresent(IncomeExpenseDetailsDO::getIncomeExpenseType,pageReqVO.getIncomeExpenseType())
.betweenIfPresent(IncomeExpenseDetailsDO::getCreateTime,pageReqVO.getCreateTime())
.orderByDesc(IncomeExpenseDetailsDO::getId));
}
/**
* 总额明细分页
* @param pageReqVO
* @return
*/
default PageResult<IncomeExpenseDetailsDO> selectTotalAmountDetailsPage(TotalAmountDetailsPageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<IncomeExpenseDetailsDO>()
.eq(IncomeExpenseDetailsDO::getDeleted, false)
.eqIfPresent(IncomeExpenseDetailsDO::getTradeType, pageReqVO.getTradeType())
.eqIfPresent(IncomeExpenseDetailsDO::getIncomeExpenseType, pageReqVO.getIncomeExpenseType())
.betweenIfPresent(IncomeExpenseDetailsDO::getCreateTime, pageReqVO.getCreateTime())
.orderByDesc(IncomeExpenseDetailsDO::getId));
}
}
@@ -1,8 +1,14 @@
package com.cf.imes.module.system.dal.mysql.pay;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsPageReqVO;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderDO;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderRechargeDetailDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
/**
* 支付订单 Mapper
@@ -12,4 +18,18 @@ import org.apache.ibatis.annotations.Mapper;
*/
@Mapper
public interface PayOrderMapper extends BaseMapper<PayOrderDO> {
/**
* 获取充值明细分页
*
* @param reqVO
* @return
*/
IPage<PayOrderRechargeDetailDO> getRechargeDetailsPage(@Param("page") IPage<PayOrderRechargeDetailDO> page, @Param("reqVO") RechargeDetailsPageReqVO reqVO);
/**
* 查询充值总额
*
* @return
*/
BigDecimal getRechargeTotalAmount();
}
@@ -18,8 +18,7 @@ import java.util.Objects;
public enum DurationUnitEnum implements IntArrayValuable, BaseEnum {
YEAR(0, ""),
MONTH(1, ""),
DAY(2, "");
MONTH(1, ""),;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DurationUnitEnum::getCode).toArray();
@@ -45,10 +44,6 @@ public enum DurationUnitEnum implements IntArrayValuable, BaseEnum {
return Objects.equals(MONTH.code, name);
}
public static boolean isDay(String name) {
return Objects.equals(DAY.code, name);
}
public static DurationUnitEnum fromStatus(Integer status) {
return Arrays.stream(values())
.filter(bean -> Objects.equals(bean.code, status))
@@ -1,7 +1,5 @@
package com.cf.imes.module.system.enums.pay;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -66,7 +64,12 @@ public enum PayProductChannelCodeEnum {
/**
* 现金+赠送金+微信
*/
BALANCE_AND_GIFT_AND_WECHAT(10);
BALANCE_AND_GIFT_AND_WECHAT(10),
/**
* 组织创建首次购买
*/
ORGAN_CREATE(11);
private final Integer code;
@@ -1,16 +1,24 @@
package com.cf.imes.module.system.service.funds.incomeandexpense;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
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.dal.dataobject.funds.purchase.PurchaseRecordDO;
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.IncomeExpenseTypeEnum;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
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.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 收支明细接口实现类
*
@@ -22,6 +30,12 @@ public class IncomeExpenseServiceImpl implements IncomeExpenseService {
@Resource
private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper;
@Resource
private PurchaseService purchaseService;
@Resource
private OrganService organService;
@Override
public void createDetail(IncomeExpenseDetailsDO incomeExpenseDetailsDO) {
incomeExpenseDetailsMapper.insert(incomeExpenseDetailsDO);
@@ -29,23 +43,49 @@ public class IncomeExpenseServiceImpl implements IncomeExpenseService {
@Override
public PageResult<BalanceDetailsRespVO> getBalanceDetailsPage(BalanceDetailsPageReqVO pageReqVO) {
if (ObjectUtil.isNull(pageReqVO.getOrganId())) {
pageReqVO.setOrganId(SecurityFrameworkUtils.getUserOrganId());
}
PageResult<IncomeExpenseDetailsDO> pageResult = incomeExpenseDetailsMapper.selectDetailsPage(pageReqVO);
if(CollUtil.isEmpty(pageResult.getList())){
List<IncomeExpenseDetailsDO> pageResultList = pageResult.getList();
if(CollUtil.isEmpty(pageResultList)){
return new PageResult<>();
}
PageResult<BalanceDetailsRespVO> result = BeanUtils.toBean(pageResult, BalanceDetailsRespVO.class);
List<BalanceDetailsRespVO> resultList = new ArrayList<>();
// 遍历构造结果
pageResultList.forEach(i -> {
BalanceDetailsRespVO respVO = new BalanceDetailsRespVO();
respVO.setBusinessNo(i.getBusinessNo());
respVO.setOrderNo(i.getOrderNo());
respVO.setCreator(i.getCreator());
respVO.setCreateTime(i.getCreateTime());
// 根据收支类型赋值对应的 支出/收入字段
result.getList().forEach(f -> {
if (IncomeExpenseTypeEnum.INCOME.getCode().equals(f.getIncomeExpenseType())) {
f.setEntryAmount(f.getCashAmountChange());
f.setEntryGiftAmount(f.getGiftAmountChange());
} else {
f.setExpensesAmount(f.getCashAmountChange());
f.setExpensesGiftAmount(f.getGiftAmountChange());
// 根据交易类型赋值对应的 金额字段
Integer tradeType = i.getTradeType();
respVO.setTradeType(tradeType);
if (TradeTypeEnum.RECHARGE.getCode().equals(tradeType)) {
respVO.setRechargeAmount(i.getCashAmountChange());
} else if (TradeTypeEnum.PRODUCT.getCode().equals(tradeType)) {
Long purchaseId = i.getPurchaseId();
if (ObjectUtil.isNotNull(purchaseId)) {
// 查询对应的购买记录
PurchaseRecordDO record = purchaseService.getRecord(purchaseId);
respVO.setProductPrice(record.getTotalAmount());
respVO.setRechargePayAmount(record.getAccountBalanceSpent());
respVO.setRechargePayAmount(record.getAlipaySpent().add(record.getWechatSpent()));
respVO.setGiftPayAmount(record.getGiftMoneySpent());
}
}
// 查询操作组织名
OrganizationDO organ = organService.getOrgan(i.getOrganId());
if (ObjectUtil.isNotNull(organ)) {
respVO.setOrganName(organ.getName());
}
resultList.add(respVO);
});
return result;
return new PageResult<>(resultList, pageResult.getTotal());
}
}
@@ -1,14 +1,11 @@
package com.cf.imes.module.system.service.funds.organamount;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.AllOrganAmountRespVO;
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.controller.admin.funds.organamount.vo.TotalAmountDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalAmountDetailsRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.organamount.OrganAmountDO;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.Map;
@@ -59,12 +56,27 @@ public interface OrganAmountService {
*/
OrganAmountRespVO getOrganAmount();
/**
* 获取组织可用金额信息
*
* @return
*/
OrganAvailableAmountRespVO getOrganAvailableAmount();
/**
* 管理端获取可用金额信息
*
* @param organId 组织id
* @return
*/
OrganAvailableAmountRespVO getManageAvailableAmount(Long organId);
/**
* 获取全部组织的余额数据
*
* @return
*/
AllOrganAmountRespVO getOrganAmountAll();
ManageAmountOverviewRespVO getOrganAmountAll();
/**
* 获取消费趋势
@@ -75,14 +87,6 @@ public interface OrganAmountService {
*/
Map<String, Object> getConsumptionTrend(OrganFundsStatisticsReqVO reqVO, boolean queryOrg);
/**
* 获取管理端总额明细
*
* @param reqVO
* @return
*/
PageResult<TotalAmountDetailsRespVO> getManageTotalAmountDetails(@Param("reqVO") TotalAmountDetailsPageReqVO reqVO);
/**
* 修正组织余额,遍历组织列表,补充system_organization_amount数据
*/
@@ -4,28 +4,22 @@ import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.exception.ServiceException;
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.framework.mybatis.core.query.LambdaUpdateWrapperX;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.executor.enums.OrderStatisticsUnit;
import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.AllOrganAmountRespVO;
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.TotalAmountDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalAmountDetailsRespVO;
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
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.incomeandexpense.IncomeExpenseDetailsMapper;
import com.cf.imes.module.system.dal.mysql.organ.OrganMapper;
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
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;
@@ -68,9 +62,6 @@ public class OrganAmountServiceImpl implements OrganAmountService {
@Resource
private OrganAmountMapper organAmountMapper;
@Resource
private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper;
@Resource
private OrganService organService;
@@ -193,7 +184,7 @@ public class OrganAmountServiceImpl implements OrganAmountService {
OrganAmountRespVO organAmountRespVO = BeanUtils.toBean(organAmountDO, OrganAmountRespVO.class);
// 查询组织最还有效的产品购买记录
// 查询组织最还有效的产品购买记录
OrgEarliestPurchaseProductRespVO orgEarliestProductDetail = purchaseService.getOrgEarliestProductDetail(organId);
if (ObjectUtil.isNotNull(orgEarliestProductDetail)) {
// 购买记录
@@ -214,61 +205,45 @@ public class OrganAmountServiceImpl implements OrganAmountService {
}
@Override
public AllOrganAmountRespVO getOrganAmountAll() {
public OrganAvailableAmountRespVO getOrganAvailableAmount() {
Long organId = SecurityFrameworkUtils.getUserOrganId();
AllOrganAmountRespVO respVO = new AllOrganAmountRespVO();
organService.validOrgan(organId);
// 所有账户的总额
QueryWrapper<IncomeExpenseDetailsDO> wrapper = new QueryWrapper<>();
wrapper.select("sum(cash_amount_change) as total");
Map<String, Object> result = incomeExpenseDetailsMapper.selectMaps(wrapper).get(0);
BigDecimal allOrganAmount = (BigDecimal) result.get("total");
// 管理端查看可开票金额
InvoiceAmountRespVO invoiceAmount = invoiceService.getManageInvoiceAmount();
respVO.setAllOrganAmount(allOrganAmount);
respVO.setToExamineAmount(invoiceAmount.getPendingInvoice());
return respVO;
OrganAmountDO organAmountDO = validOrganAmount(organId);
return BeanUtils.toBean(organAmountDO, OrganAvailableAmountRespVO.class);
}
@Override
public PageResult<TotalAmountDetailsRespVO> getManageTotalAmountDetails(TotalAmountDetailsPageReqVO reqVO) {
PageResult<IncomeExpenseDetailsDO> pageResult = incomeExpenseDetailsMapper.selectTotalAmountDetailsPage(reqVO);
public OrganAvailableAmountRespVO getManageAvailableAmount(Long organId) {
// 查询固定组织的可用金额
if (ObjectUtil.isNotNull(organId)) {
organService.validOrgan(organId);
List<TotalAmountDetailsRespVO> resultList = new ArrayList<>();
List<IncomeExpenseDetailsDO> list = pageResult.getList();
for (IncomeExpenseDetailsDO detailsDO : list) {
TotalAmountDetailsRespVO totalAmountDetailsRespVO = new TotalAmountDetailsRespVO();
totalAmountDetailsRespVO.setBusinessNo(detailsDO.getBusinessNo());
// 根据交易类型赋值对应的金额
Integer tradeType = detailsDO.getTradeType();
totalAmountDetailsRespVO.setTradeType(tradeType);
if (TradeTypeEnum.isRecharge(tradeType)) {
totalAmountDetailsRespVO.setRechargeAmount(detailsDO.getCashAmountChange());
totalAmountDetailsRespVO.setProductAmount(BigDecimal.ZERO);
}
if (TradeTypeEnum.isProduct(tradeType)) {
totalAmountDetailsRespVO.setRechargeAmount(BigDecimal.ZERO);
totalAmountDetailsRespVO.setProductAmount(detailsDO.getCashAmountChange());
}
totalAmountDetailsRespVO.setIncomeExpenseType(detailsDO.getIncomeExpenseType());
totalAmountDetailsRespVO.setCashAmount(BigDecimal.ZERO);
totalAmountDetailsRespVO.setAccountCashBalance(detailsDO.getAmount());
totalAmountDetailsRespVO.setOperatorName(detailsDO.getCreator());
OrganizationDO organ = organService.getOrgan(detailsDO.getOrganId());
if (ObjectUtil.isNotNull(organ)) {
totalAmountDetailsRespVO.setOrganName(organ.getName());
}
totalAmountDetailsRespVO.setCreateTime(detailsDO.getCreateTime());
OrganAmountDO organAmountDO = validOrganAmount(organId);
resultList.add(totalAmountDetailsRespVO);
return BeanUtils.toBean(organAmountDO, OrganAvailableAmountRespVO.class);
}
// 查询所有组织的可用金额
return organAmountMapper.getTotalAvailableAmount();
}
return new PageResult<>(resultList, pageResult.getTotal());
@Override
public ManageAmountOverviewRespVO getOrganAmountAll() {
ManageAmountOverviewRespVO respVO = new ManageAmountOverviewRespVO();
TotalSalesAmountRespVO totalSales = purchaseService.getTotalSales();
// 销售总额
respVO.setTotalSalesAmount(totalSales.getAmount());
respVO.setTotalSalesGiftAmount(totalSales.getGiftAmount());
// 充值余额
respVO.setRechargeBalance(organAmountMapper.getTotalRechargeAmount());
// 可开票金额
respVO.setToExamineAmount(invoiceService.getManageInvoiceAmount().getPendingInvoice());
return respVO;
}
@Override
@@ -1,12 +1,18 @@
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.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;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganCreateProductPurchaseReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
/**
* @author 软件购买接口
@@ -58,4 +64,39 @@ public interface PurchaseService {
* @return
*/
BigDecimal getInvoicingAmount(Long organId);
/**
* 创建组织初始化(创建)时的购买记录
*
* @param organId
* @param productPurchaseReqVOS
*/
void createOrgInitProductPurchaseRecord(Long organId, List<OrganCreateProductPurchaseReqVO> productPurchaseReqVOS);
/**
* 查询组织下的产品购买记录
*
* @param organIds
* @return
*/
List<PurchaseRecordDO> getOrgPurchaseList(Set<Long> organIds);
/**
* 查询销售总额
*/
TotalSalesAmountRespVO getTotalSales();
/**
* 查询购买记录中的现金使用金额总数
*
* @return
*/
BigDecimal getTotalRechargeUsageAmount();
/**
* 查询管理端销售明细分页
*
* @return
*/
PageResult<SalesDetailRespVO> getManageSalesDetailsPage(SalesDetailsPageReqVO pageReqVO);
}
@@ -1,26 +1,43 @@
package com.cf.imes.module.system.service.funds.purchase;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
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.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.organamount.vo.TotalSalesAmountRespVO;
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;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganCreateProductPurchaseReqVO;
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.organ.OrganizationDO;
import com.cf.imes.module.system.dal.mysql.funds.products.ProductsDetailMapper;
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.PayProductChannelCodeEnum;
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.products.ProductsDetailService;
import com.cf.imes.module.system.service.organ.OrganService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author 软件购买接口 实现类
@@ -35,6 +52,16 @@ public class PurchaseServiceImpl implements PurchaseService {
@Resource
private ProductsDetailMapper productsDetailMapper;
@Resource
private ProductsDetailService productsDetailService;
@Resource
private MybatisIdProperties mybatisIdProperties;
@Resource
@Lazy
private OrganService organService;
@Override
public PurchaseRecordDO getRecord(Long id) {
return purchaseRecordMapper.selectById(id);
@@ -70,11 +97,11 @@ public class PurchaseServiceImpl implements PurchaseService {
@Override
public OrgEarliestPurchaseProductRespVO getOrgEarliestProductDetail(Long organId) {
// 查询购买记录中还有效的最一条
// 查询购买记录中还有效的最一条
PurchaseRecordDO purchaseRecordDO = purchaseRecordMapper.selectOne(new LambdaQueryWrapper<PurchaseRecordDO>()
.eq(PurchaseRecordDO::getOrganId, organId)
.gt(PurchaseRecordDO::getEndTime, LocalDateTime.now())
.orderByAsc(PurchaseRecordDO::getCreateTime)
.orderByDesc(PurchaseRecordDO::getCreateTime)
.last("limit 1"));
if (ObjectUtil.isNotNull(purchaseRecordDO)) {
return new OrgEarliestPurchaseProductRespVO(purchaseRecordDO, productsDetailMapper.selectById(purchaseRecordDO.getProductDetailsId()));
@@ -86,4 +113,74 @@ public class PurchaseServiceImpl implements PurchaseService {
public BigDecimal getInvoicingAmount(Long organId) {
return purchaseRecordMapper.getInvoicingAmount(organId);
}
@Override
public void createOrgInitProductPurchaseRecord(Long organId, List<OrganCreateProductPurchaseReqVO> productPurchaseReqVOS) {
for (OrganCreateProductPurchaseReqVO purchaseReqVO : productPurchaseReqVOS) {
// 1、校验定价
ProductsDetailDO productsDetailDO = productsDetailService.validateProductDetailsExists(purchaseReqVO.getProductDetailsId());
// 2、校验产品
Long productId = productsDetailDO.getProductId();
ProductsDO productsDO = productsDetailService.validateProductExist(productId);
// 3、创建购买记录
long purchaseId = IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId();
PurchaseRecordDO purchaseRecordDO = PurchaseRecordDO.builder()
.id(purchaseId)
.organId(organId)
.productId(productId)
.productName(productsDO.getProductName())
.productDetailsId(productsDetailDO.getId())
.purchaseDuration(productsDetailDO.getDuration())
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.giftDuration(productsDetailDO.getGiftDuration())
.giftDurationUnit(productsDetailDO.getGiftDurationUnit())
.startTime(LocalDate.now())
.endTime(purchaseReqVO.getProductExpireDate())
.paymentMethod(PayProductChannelCodeEnum.ORGAN_CREATE.getCode())
.totalAmount(purchaseReqVO.getPrice())
.isInvocing(InvoiceStatusEnum.INVOICABLE.getCode())
.build();
createRecord(purchaseRecordDO);
}
}
@Override
public List<PurchaseRecordDO> getOrgPurchaseList(Set<Long> organIds) {
return purchaseRecordMapper.selectList(new LambdaQueryWrapper<PurchaseRecordDO>().in(PurchaseRecordDO::getOrganId, organIds));
}
@Override
public TotalSalesAmountRespVO getTotalSales() {
return purchaseRecordMapper.getTotalSales();
}
@Override
public BigDecimal getTotalRechargeUsageAmount() {
return purchaseRecordMapper.getTotalRechargeUsageAmount();
}
@Override
public PageResult<SalesDetailRespVO> getManageSalesDetailsPage(SalesDetailsPageReqVO reqVO) {
// 分页查询
PageResult<PurchaseRecordDO> salesDetailPage = purchaseRecordMapper.getSaleDetailsPage(reqVO);
// 构建回调数据
List<SalesDetailRespVO> resultList = new ArrayList<>();
for (PurchaseRecordDO detailDO : salesDetailPage.getList()) {
SalesDetailRespVO respVO = BeanUtils.toBean(detailDO, SalesDetailRespVO.class);
// 销售目前都是产品购买
respVO.setTradeType(TradeTypeEnum.PRODUCT.getCode());
// 充值支付=支付宝/微信
respVO.setRechargeSpent(detailDO.getAlipaySpent().add(detailDO.getWechatSpent()));
// 查询组织名称
OrganizationDO organ = organService.getOrgan(detailDO.getOrganId());
if (ObjectUtil.isNotNull(organ)) {
respVO.setOrganName(organ.getName());
}
resultList.add(respVO);
}
return new PageResult<>(resultList, salesDetailPage.getTotal());
}
}
@@ -0,0 +1,28 @@
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.RechargeDetailRespVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsBalanceInfoRespVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsPageReqVO;
/**
* 充值明细 Service 接口
*
* @author Gqr
* @since 2025/9/11 16:20
*/
public interface RechargeDetailsService {
/**
* 查询充值明细分页
*
* @return
*/
PageResult<RechargeDetailRespVO> getRechargeDetailsPage(RechargeDetailsPageReqVO reqVO);
/**
* 获取管理端充值余额信息
*
* @return
*/
RechargeDetailsBalanceInfoRespVO getManageRechargeDetailsBalanceInfo();
}
@@ -0,0 +1,38 @@
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.RechargeDetailRespVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsBalanceInfoRespVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsPageReqVO;
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 PageResult<RechargeDetailRespVO> getRechargeDetailsPage(RechargeDetailsPageReqVO reqVO) {
return payOrderService.getRechargeDetailsPage(reqVO);
}
@Override
public RechargeDetailsBalanceInfoRespVO getManageRechargeDetailsBalanceInfo() {
RechargeDetailsBalanceInfoRespVO rechargeDetailsBalanceInfoRespVO = new RechargeDetailsBalanceInfoRespVO();
rechargeDetailsBalanceInfoRespVO.setRechargeAmount(payOrderService.getRechargeTotalAmount());
rechargeDetailsBalanceInfoRespVO.setRechargeUsageAmount(purchaseService.getTotalRechargeUsageAmount());
return rechargeDetailsBalanceInfoRespVO;
}
}
@@ -8,6 +8,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.collection.CollectionUtils;
import com.cf.imes.framework.common.util.date.DateUtils;
import com.cf.imes.framework.common.util.json.JsonUtils;
@@ -21,11 +22,11 @@ import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsIsLapseRespDTO;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsReqDTO;
import com.cf.imes.module.system.constants.permission.InternalRoleConstants;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganCreateProductPurchaseReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganPageReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganRespVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganSaveReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganSimpleRespVO;
import com.cf.imes.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
import com.cf.imes.module.system.controller.admin.systemconfig.vo.ProcessSchemeConfig;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.JwtConfig;
import com.cf.imes.module.system.controller.admin.user.vo.user.UserSaveReqVO;
@@ -52,7 +53,7 @@ import com.cf.imes.module.system.dal.mysql.systemconfig.*;
import com.cf.imes.module.system.dal.mysql.tokenconfig.TokenConfigMapper;
import com.cf.imes.module.system.enums.config.SystemConfigTypeEnum;
import com.cf.imes.module.system.enums.permission.RoleCodeEnum;
import com.cf.imes.module.system.enums.permission.RoleTypeEnum;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
import com.cf.imes.module.system.service.organ.handler.OrganInfoHandler;
import com.cf.imes.module.system.service.organ.handler.OrganMenuHandler;
import com.cf.imes.module.system.service.permission.MenuService;
@@ -155,6 +156,8 @@ public class OrganServiceImpl implements OrganService {
@Resource
private OrganAmountMapper organAmountMapper;
@Resource
private PurchaseService purchaseService;
@Override
public List<Long> getOrganIdList() {
@@ -202,12 +205,13 @@ public class OrganServiceImpl implements OrganService {
// 校验组织域名是否重复
validTenantWebsiteDuplicate(createReqVO.getWebsite(), null);
// 校验组织手机号是否重复
validContactMobileDuplicate(createReqVO.getContactMobile(),null);
// 校验套餐被禁用
TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(createReqVO.getPackageId());
validContactMobileDuplicate(createReqVO.getOrgAdminMobile(),null);
// 创建组织
OrganizationDO tenant = BeanUtils.toBean(createReqVO, OrganizationDO.class);
// 管理员姓名/手机 适配 原联系人
tenant.setContactName(createReqVO.getOrgAdminName());
tenant.setContactMobile(createReqVO.getOrgAdminMobile());
String pinyinFull = PinYinUtils.convertToPinyin(tenant.getName());
if(CharSequenceUtil.isNotBlank(pinyinFull)) {
pinyinFull = pinyinFull.replace(" ", "");
@@ -226,30 +230,30 @@ public class OrganServiceImpl implements OrganService {
tenant.setTableNo(organId.intValue() % 256);
organMapper.updateById(tenant);
// 创建组织的管理员
OrganUtils.execute(organId, () -> {
// 创建角色
/*Long roleId = createRole(tenantPackage, organId);*/
// 创建用户,并分配角色
Long userId = createUser(InternalRoleConstants.ORGAN_ADMIN_ROLE_ID, createReqVO, organId);
// 修改组织的管理员
organMapper.updateById(new OrganizationDO().setId(tenant.getId()).setContactUserId(userId));
});
// 1、创建用户,并分配角色
Long userId = createUser(InternalRoleConstants.ORGAN_ADMIN_ROLE_ID, createReqVO, organId);
// 2、修改组织的管理员
organMapper.updateById(new OrganizationDO().setId(tenant.getId()).setContactUserId(userId));
// 往组织机台授权表新增信息
MachineLimitDO machineLimitDO = MachineLimitDO.builder()
.organId(tenant.getId())
.organId(organId)
.build();
machineLimitMapper.insert(machineLimitDO);
// 复制系统配置里的相关配置
copySystemConfig(tenant.getId());
copySystemConfig(organId);
// 创建组织套餐
organAmountMapper.insert(OrganAmountDO.builder()
.organId(tenant.getId())
.organId(organId)
.build());
// 创建产品购买记录
List<OrganCreateProductPurchaseReqVO> productPurchaseReqVOS = createReqVO.getProductPurchaseReqVOS();
AssertUtils.notEmpty(productPurchaseReqVOS, ORGAN_CREATE_PRODUCTLIST_EMPTY_ERROR);
purchaseService.createOrgInitProductPurchaseRecord(organId, productPurchaseReqVOS);
return tenant.getId();
}
@@ -263,17 +267,6 @@ public class OrganServiceImpl implements OrganService {
return userId;
}
private Long createRole(TenantPackageDO tenantPackage, Long organId) {
// 创建角色
RoleSaveReqVO reqVO = new RoleSaveReqVO();
reqVO.setName(RoleCodeEnum.TENANT_ADMIN.getName()).setCode(RoleCodeEnum.TENANT_ADMIN.getCode())
.setSort(0).setRemark("系统自动生成").setOrganId(organId);
Long roleId = roleService.createRole(reqVO, RoleTypeEnum.SYSTEM.getType());
// 分配权限
permissionService.assignRoleMenu(roleId, tenantPackage.getMenuIds(), organId);
return roleId;
}
@Override
@DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
public void updateOrgan(OrganSaveReqVO updateReqVO) {
@@ -285,7 +278,7 @@ public class OrganServiceImpl implements OrganService {
// 校验组织域名是否重复
validTenantWebsiteDuplicate(updateReqVO.getWebsite(), organId);
// 校验组织手机号是否重复
validContactMobileDuplicate(updateReqVO.getContactMobile(),organId);
validContactMobileDuplicate(updateReqVO.getOrgAdminMobile(),organId);
// 校验套餐被禁用
TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(updateReqVO.getPackageId());
if(!Objects.equals(tenant.getName(), updateReqVO.getName())) {
@@ -300,12 +293,12 @@ public class OrganServiceImpl implements OrganService {
// 如果手机号更新,需要同步更新 token 管理的 token
if(!Objects.equals(tenant.getContactMobile(), updateReqVO.getContactMobile())){
if(!Objects.equals(tenant.getContactMobile(), updateReqVO.getOrgAdminMobile())){
List<TokenConfigDO> tokenConfigDOS = tokenConfigMapper.selectConfigByOrganId(organId);
if(CollUtil.isNotEmpty(tokenConfigDOS)) {
tokenConfigDOS.forEach(f -> {
f.setAppToken(generateBaseToken(organId, updateReqVO.getContactMobile(), f.getAppType(), jwtConfig.getSecret()));
f.setAppToken(generateBaseToken(organId, updateReqVO.getOrgAdminMobile(), f.getAppType(), jwtConfig.getSecret()));
});
tokenConfigMapper.updateBatch(tokenConfigDOS);
}
@@ -1,9 +1,13 @@
package com.cf.imes.module.system.service.pay;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailRespVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayProductOrderUnifiedReqVO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayRechargeOrderReqVO;
import java.math.BigDecimal;
import java.util.Map;
/**
@@ -51,4 +55,19 @@ public interface PayOrderService {
* @return
*/
int expirePayOrder();
/**
* 查询充值明细分页
*
* @param reqVO
* @return
*/
PageResult<RechargeDetailRespVO> getRechargeDetailsPage(RechargeDetailsPageReqVO reqVO);
/**
* 管理端查询充值总额
*
* @return
*/
BigDecimal getRechargeTotalAmount();
}
@@ -6,24 +6,32 @@ import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
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.json.JsonUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.common.util.validation.ValidationUtils;
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.pay.config.ChenfengAlipayConfig;
import com.cf.imes.framework.pay.config.ChenfengPayConfig;
import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailRespVO;
import com.cf.imes.module.system.controller.admin.funds.recharge.vo.RechargeDetailsPageReqVO;
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.organ.OrganizationDO;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderRechargeDetailDO;
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;
@@ -45,6 +53,7 @@ import com.cf.imes.module.system.service.funds.incomeandexpense.IncomeExpenseSer
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;
@@ -61,6 +70,7 @@ import jakarta.validation.Validator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -120,15 +130,15 @@ public class PayOrderServiceImpl implements PayOrderService {
@Resource
private PurchaseService purchaseService;
@Resource
private SnowflakeIdWorker3rd snowflakeIdWorker3rd;
@Resource
private MybatisIdProperties mybatisIdProperties;
@Resource
private RechargeActiveService rechargeActiveService;
@Resource
private OrganService organService;
@Override
@Transactional(rollbackFor = Exception.class)
public PayOrderRespDTO productPay(PayProductOrderUnifiedReqVO payProductOrderUnifiedReqVO) {
@@ -146,7 +156,7 @@ public class PayOrderServiceImpl implements PayOrderService {
OrganAmountDO organAmount = organAmountService.validOrganAmount(organId);
// 根据购买类型做价格处理
PayProductProcessor payProductProcessor = new PayProductProcessor(productsDO, productsDetailDO, organAmount, organId, snowflakeIdWorker3rd, payConfig, mybatisIdProperties);
PayProductProcessor payProductProcessor = new PayProductProcessor(productsDO, productsDetailDO, organAmount, organId, payConfig, mybatisIdProperties);
ProductProcessorRespVO productProcessorRespVO = payProductProcessor.processPayment(PayProductChannelCodeEnum.fromType(payProductOrderUnifiedReqVO.getProductChannelCode()));
// 记录入库,如果有外部支付发起请求二维码
@@ -511,7 +521,8 @@ public class PayOrderServiceImpl implements PayOrderService {
// 2.新增收支明细
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(payNo)
.orderNo(payNo)
.businessNo(LocalDateTimeUtils.formatNow())
.tradeType(TradeTypeEnum.RECHARGE.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.INCOME.getCode())
.cashAmountChange(price)
@@ -628,7 +639,8 @@ public class PayOrderServiceImpl implements PayOrderService {
// 2、新增退回的收支记录
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, record.getId()))
.orderNo(String.valueOf(record.getId()))
.businessNo(LocalDateTimeUtils.formatNow())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.INCOME.getCode())
.cashAmountChange(accountBalanceSpent)
@@ -697,4 +709,42 @@ public class PayOrderServiceImpl implements PayOrderService {
return false;
}
}
@Override
public PageResult<RechargeDetailRespVO> getRechargeDetailsPage(RechargeDetailsPageReqVO reqVO) {
// 分页查询
Page<PayOrderRechargeDetailDO> page = new Page<>(reqVO.getPageNo(), reqVO.getPageSize());
IPage<PayOrderRechargeDetailDO> rechargeDetailsPage = payOrderMapper.getRechargeDetailsPage(page, reqVO);
// 构建回调数据
List<RechargeDetailRespVO> resultList = new ArrayList<>();
for (PayOrderRechargeDetailDO detailDO : rechargeDetailsPage.getRecords()) {
RechargeDetailRespVO respVO = BeanUtils.toBean(detailDO, RechargeDetailRespVO.class);
// 根据是否关联购买记录判断是充值还是购买软件
if (ObjectUtil.isNotNull(detailDO.getPurchaseId())) {
respVO.setTradeType(TradeTypeEnum.PRODUCT.getCode());
// 产品购买有充值记录的,充值支付就是支付单的金额
respVO.setRechargeSpent(detailDO.getPrice());
} else {
respVO.setTradeType(TradeTypeEnum.RECHARGE.getCode());
BigDecimal zero = BigDecimal.ZERO;
respVO.setRechargeSpent(zero);
respVO.setTotalAmount(zero);
respVO.setAccountBalanceSpent(zero);
respVO.setGiftMoneySpent(zero);
}
OrganizationDO organ = organService.getOrgan(detailDO.getOrganId());
if (ObjectUtil.isNotNull(organ)) {
respVO.setOrganName(organ.getName());
}
resultList.add(respVO);
}
return new PageResult<>(resultList, rechargeDetailsPage.getTotal());
}
@Override
public BigDecimal getRechargeTotalAmount() {
return payOrderMapper.getRechargeTotalAmount();
}
}
@@ -4,6 +4,7 @@ import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
import com.cf.imes.framework.pay.config.ChenfengPayConfig;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
@@ -26,6 +27,7 @@ import com.cf.imes.module.system.framework.snowflake.config.MybatisIdProperties;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_PRODUCT_AVAILABLE_BALANCE_INSUFFICIENT;
@@ -48,20 +50,16 @@ public class PayProductProcessor {
private Long organId;
private SnowflakeIdWorker3rd snowflakeIdWorker3rd;
private ChenfengPayConfig payConfig;
private MybatisIdProperties mybatisIdProperties;
public PayProductProcessor(ProductsDO productsDO, ProductsDetailDO productsDetailDO, OrganAmountDO organAmountDO,
Long organId, SnowflakeIdWorker3rd snowflakeIdWorker3rd, ChenfengPayConfig payConfig,
MybatisIdProperties mybatisIdProperties) {
Long organId, ChenfengPayConfig payConfig, MybatisIdProperties mybatisIdProperties) {
this.productsDO = productsDO;
this.productsDetailDO = productsDetailDO;
this.organAmountDO = organAmountDO;
this.organId = organId;
this.snowflakeIdWorker3rd = snowflakeIdWorker3rd;
this.payConfig = payConfig;
this.mybatisIdProperties = mybatisIdProperties;
}
@@ -129,7 +127,7 @@ public class PayProductProcessor {
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.giftDuration(productsDetailDO.getGiftDuration())
.giftDurationUnit(productsDetailDO.getGiftDurationUnit())
.startTime(LocalDateTime.now())
.startTime(LocalDate.now())
.paymentMethod(PayProductChannelCodeEnum.BALANCE_ONLY.getCode())
.totalAmount(price)
.accountBalanceSpent(price)
@@ -144,7 +142,8 @@ public class PayProductProcessor {
BigDecimal giftAmount = organAmountDO.getGiftAmount();
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.businessNo(LocalDateTimeUtils.formatNow())
.purchaseId(purchaseRecordDO.getId())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
@@ -182,7 +181,7 @@ public class PayProductProcessor {
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.giftDuration(productsDetailDO.getGiftDuration())
.giftDurationUnit(productsDetailDO.getGiftDurationUnit())
.startTime(LocalDateTime.now())
.startTime(LocalDate.now())
.paymentMethod(PayProductChannelCodeEnum.BALANCE_ONLY.getCode())
.totalAmount(price)
.accountBalanceSpent(price)
@@ -197,7 +196,8 @@ public class PayProductProcessor {
BigDecimal amount = organAmountDO.getAmount();
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.businessNo(LocalDateTimeUtils.formatNow())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseRecordDO.getId())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
@@ -220,9 +220,10 @@ public class PayProductProcessor {
* @return
*/
private ProductProcessorRespVO payByAlipay(BigDecimal price) {
long purchaseId = IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId();
// 新增购买记录
PurchaseRecordDO purchaseRecordDO = PurchaseRecordDO.builder()
.id(IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId())
.id(purchaseId)
.organId(organId)
.organId(organId)
.productId(productsDO.getId())
@@ -232,7 +233,7 @@ public class PayProductProcessor {
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.giftDuration(productsDetailDO.getGiftDuration())
.giftDurationUnit(productsDetailDO.getGiftDurationUnit())
.startTime(LocalDateTime.now())
.startTime(LocalDate.now())
.paymentMethod(PayProductChannelCodeEnum.BALANCE_ONLY.getCode())
.totalAmount(price)
.alipaySpent(price)
@@ -242,7 +243,7 @@ public class PayProductProcessor {
purchaseRecordDO.getGiftDuration(), purchaseRecordDO.getGiftDurationUnit()));
// 新增第三方支付订单
PayOrderDO payOrderDO = goExternalPay(price, PayChannelCodeEnum.ALIPAY_PC);
PayOrderDO payOrderDO = goExternalPay(purchaseId, price, PayChannelCodeEnum.ALIPAY_PC);
return new ProductProcessorRespVO(purchaseRecordDO, null, payOrderDO, null);
}
@@ -254,8 +255,9 @@ public class PayProductProcessor {
*/
private ProductProcessorRespVO payByWechat(BigDecimal price) {
// 新增购买记录
long purchaseId = IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId();
PurchaseRecordDO purchaseRecordDO = PurchaseRecordDO.builder()
.id(IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId())
.id(purchaseId)
.organId(organId)
.productId(productsDO.getId())
.productName(productsDO.getProductName())
@@ -264,7 +266,7 @@ public class PayProductProcessor {
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.giftDuration(productsDetailDO.getGiftDuration())
.giftDurationUnit(productsDetailDO.getGiftDurationUnit())
.startTime(LocalDateTime.now())
.startTime(LocalDate.now())
.paymentMethod(PayProductChannelCodeEnum.BALANCE_ONLY.getCode())
.totalAmount(price)
.wechatSpent(price)
@@ -274,7 +276,7 @@ public class PayProductProcessor {
purchaseRecordDO.getGiftDuration(), purchaseRecordDO.getGiftDurationUnit()));
// 新增第三方支付订单
PayOrderDO payOrderDO = goExternalPay(price, PayChannelCodeEnum.WECHAT_NATIVE);
PayOrderDO payOrderDO = goExternalPay(purchaseId, price, PayChannelCodeEnum.WECHAT_NATIVE);
return new ProductProcessorRespVO(purchaseRecordDO, null, payOrderDO, null);
}
@@ -302,7 +304,7 @@ public class PayProductProcessor {
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.giftDuration(productsDetailDO.getGiftDuration())
.giftDurationUnit(productsDetailDO.getGiftDurationUnit())
.startTime(LocalDateTime.now())
.startTime(LocalDate.now())
.paymentMethod(PayProductChannelCodeEnum.BALANCE_AND_GIFT.getCode())
.totalAmount(price)
.isInvocing(InvoiceStatusEnum.INVOICABLE.getCode())
@@ -336,7 +338,8 @@ public class PayProductProcessor {
BigDecimal newGift = gift.subtract(usedGift);
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.businessNo(LocalDateTimeUtils.formatNow())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseRecordDO.getId())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
@@ -375,7 +378,7 @@ public class PayProductProcessor {
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.giftDuration(productsDetailDO.getGiftDuration())
.giftDurationUnit(productsDetailDO.getGiftDurationUnit())
.startTime(LocalDateTime.now())
.startTime(LocalDate.now())
.paymentMethod(payChannelCodeEnum.ALIPAY_PC.equals(payChannelCodeEnum) ? PayProductChannelCodeEnum.BALANCE_AND_GIFT_AND_ALIPAY.getCode() : PayProductChannelCodeEnum.BALANCE_AND_GIFT_AND_WECHAT.getCode())
.totalAmount(price)
.build();
@@ -396,7 +399,8 @@ public class PayProductProcessor {
BigDecimal giftAmount = organAmountDO.getGiftAmount();
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.businessNo(LocalDateTimeUtils.formatNow())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseRecordDO.getId())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
@@ -409,7 +413,7 @@ public class PayProductProcessor {
// 剩下走第三方
PayOrderDO payOrderDO = null;
if (remaining.compareTo(BigDecimal.ZERO) > 0) {
payOrderDO = goExternalPay(remaining, payChannelCodeEnum);
payOrderDO = goExternalPay(purchaseId, remaining, payChannelCodeEnum);
// 记录第三方支付支出
if (PayChannelCodeEnum.ALIPAY_PC.equals(payChannelCodeEnum)) {
purchaseRecordDO.setAlipaySpent(remaining);
@@ -435,8 +439,9 @@ public class PayProductProcessor {
BigDecimal usedGift = BigDecimal.ZERO;
// 新增购买记录
long purchaseId = IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId();
PurchaseRecordDO purchaseRecordDO = PurchaseRecordDO.builder()
.id(IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId())
.id(purchaseId)
.organId(organId)
.productId(productsDO.getId())
.productName(productsDO.getProductName())
@@ -445,7 +450,7 @@ public class PayProductProcessor {
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.giftDuration(productsDetailDO.getGiftDuration())
.giftDurationUnit(productsDetailDO.getGiftDurationUnit())
.startTime(LocalDateTime.now())
.startTime(LocalDate.now())
.paymentMethod(payChannelCodeEnum.ALIPAY_PC.equals(payChannelCodeEnum) ? PayProductChannelCodeEnum.GIFT_AND_ALIPAY.getCode() : PayProductChannelCodeEnum.GIFT_AND_WECHAT.getCode())
.totalAmount(price)
.build();
@@ -467,7 +472,9 @@ public class PayProductProcessor {
BigDecimal amount = organAmountDO.getAmount();
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.purchaseId(purchaseRecordDO.getId())
.businessNo(LocalDateTimeUtils.formatNow())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseId)
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
.giftAmountChange(usedGift)
@@ -479,7 +486,7 @@ public class PayProductProcessor {
// 剩下走第三方
PayOrderDO payOrderDO = null;
if (remaining.compareTo(BigDecimal.ZERO) > 0) {
goExternalPay(remaining, payChannelCodeEnum);
payOrderDO = goExternalPay(purchaseId, remaining, payChannelCodeEnum);
// 记录第三方支付支出
if (PayChannelCodeEnum.ALIPAY_PC.equals(payChannelCodeEnum)) {
purchaseRecordDO.setAlipaySpent(remaining);
@@ -518,7 +525,7 @@ public class PayProductProcessor {
.purchaseDurationUnit(productsDetailDO.getDurationUnit())
.giftDuration(productsDetailDO.getGiftDuration())
.giftDurationUnit(productsDetailDO.getGiftDurationUnit())
.startTime(LocalDateTime.now())
.startTime(LocalDate.now())
.paymentMethod(PayProductChannelCodeEnum.BALANCE_AND_GIFT.getCode())
.totalAmount(price)
.build();
@@ -546,8 +553,9 @@ public class PayProductProcessor {
BigDecimal newGift = gift.subtract(usedGift);
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseRecordDO.getId())
.businessNo(LocalDateTimeUtils.formatNow())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseId)
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
.cashAmountChange(usedBalance)
@@ -560,7 +568,7 @@ public class PayProductProcessor {
// 剩下走第三方
PayOrderDO payOrderDO = null;
if (remaining.compareTo(BigDecimal.ZERO) > 0) {
payOrderDO = goExternalPay(remaining, payChannelCodeEnum);
payOrderDO = goExternalPay(purchaseId, remaining, payChannelCodeEnum);
// 记录第三方支付支出
if (PayChannelCodeEnum.ALIPAY_PC.equals(payChannelCodeEnum)) {
purchaseRecordDO.setAlipaySpent(remaining);
@@ -578,11 +586,12 @@ public class PayProductProcessor {
/**
* 外部支付
*
* @param purchaseId
* @param price
* @param payChannelCodeEnum
* @return
*/
private PayOrderDO goExternalPay(BigDecimal price, PayChannelCodeEnum payChannelCodeEnum) {
private PayOrderDO goExternalPay(Long purchaseId, BigDecimal price, PayChannelCodeEnum payChannelCodeEnum) {
PayOrderDO payOrderDO = new PayOrderDO();
Long payOrderId = IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId();
@@ -596,6 +605,7 @@ public class PayProductProcessor {
payOrderDO.setSubject(productsDO.getProductName());
payOrderDO.setChannelCode(payChannelCodeEnum);
payOrderDO.setOrganId(organId);
payOrderDO.setPurchaseId(purchaseId);
return payOrderDO;
}
@@ -609,7 +619,7 @@ public class PayProductProcessor {
* @param giftDurationUnit
* @return
*/
private static LocalDateTime calculateEndTime(LocalDateTime startTime, String duration, Integer durationUnit,
private static LocalDate calculateEndTime(LocalDate startTime, String duration, Integer durationUnit,
String giftDuration, Integer giftDurationUnit) {
// 加正常时间
@@ -633,14 +643,12 @@ public class PayProductProcessor {
* @param unit
* @return
*/
private static LocalDateTime addTime(LocalDateTime time, int duration, int unit) {
private static LocalDate addTime(LocalDate time, int duration, int 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;
}
@@ -96,9 +96,6 @@ public class AdminUserServiceImpl implements AdminUserService {
@Lazy // 延迟,避免循环依赖报错
private OrganService organService;
// @Resource
// private UserPostMapper userPostMapper;
@Resource
private FileApi fileApi;
@@ -154,11 +151,6 @@ public class AdminUserServiceImpl implements AdminUserService {
user.setPinyinFull(pinyinFull);
user.setPinyinInitial(PinYinUtils.convertFirstChar(user.getNickname()));
userMapper.insert(user);
// // 插入关联岗位
// if (CollUtil.isNotEmpty(user.getPostIds())) {
// userPostMapper.insertBatch(convertList(user.getPostIds(),
// postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId)));
// }
return user.getId();
}
@@ -232,23 +224,6 @@ public class AdminUserServiceImpl implements AdminUserService {
}
}
// private void updateUserPost(UserSaveReqVO reqVO, AdminUserDO updateObj) {
// Long userId = reqVO.getId();
// Set<Long> dbPostIds = convertSet(userPostMapper.selectListByUserId(userId), UserPostDO::getPostId);
// // 计算新增和删除的岗位编号
// Set<Long> postIds = CollUtil.emptyIfNull(updateObj.getPostIds());
// Collection<Long> createPostIds = CollUtil.subtract(postIds, dbPostIds);
// Collection<Long> deletePostIds = CollUtil.subtract(dbPostIds, postIds);
// // 执行新增和删除。对于已经授权的菜单,不用做任何处理
// if (!CollUtil.isEmpty(createPostIds)) {
// userPostMapper.insertBatch(convertList(createPostIds,
// postId -> new UserPostDO().setUserId(userId).setPostId(postId)));
// }
// if (!CollUtil.isEmpty(deletePostIds)) {
// userPostMapper.deleteByUserIdAndPostId(userId, deletePostIds);
// }
// }
@Override
public void updateUserLogin(Long id, String loginIp) {
userMapper.update(new LambdaUpdateWrapper<AdminUserDO>()
@@ -372,8 +347,6 @@ public class AdminUserServiceImpl implements AdminUserService {
if (deleteNum > 0) {
// 删除用户关联数据
permissionService.processUserDeleted(id);
// // 删除用户岗位
// userPostMapper.deleteByUserId(id);
// 移除用户token
scanAndCompareUserAndDelToken(String.format(OAUTH2_ACCESS_TOKEN, "*"), id);
}
@@ -390,8 +363,6 @@ public class AdminUserServiceImpl implements AdminUserService {
if (deleteNum > 0) {
// 删除用户关联数据
permissionService.processUserDeleted(userId);
// // 删除用户岗位
// userPostMapper.deleteByUserId(userId);
}
}
}
@@ -407,8 +378,6 @@ public class AdminUserServiceImpl implements AdminUserService {
if (deleteNum > 0) {
// 删除用户关联数据
permissionService.processUserDeleted(userId);
// // 删除用户岗位
// userPostMapper.deleteByUserId(userId);
}
}
}
@@ -471,11 +440,6 @@ public class AdminUserServiceImpl implements AdminUserService {
if (CollUtil.isEmpty(postIds)) {
return Collections.emptyList();
}
// Set<Long> userIds = convertSet(userPostMapper.selectListByPostIds(postIds), UserPostDO::getUserId);
// if (CollUtil.isEmpty(userIds)) {
// return Collections.emptyList();
// }
// return userMapper.selectBatchIds(userIds);
return null;
}
@@ -29,4 +29,19 @@
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>
@@ -0,0 +1,29 @@
<?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.pay.PayOrderMapper">
<select id="getRechargeDetailsPage" resultType="com.cf.imes.module.system.dal.dataobject.pay.PayOrderRechargeDetailDO">
select o.id, o.organ_id, o.pay_no, o.price, o.purchase_id, o.creator, o.create_time, p.total_amount, p.account_balance_spent, p.gift_money_spent
from pay_order o
left join purchase_record p on o.purchase_id = p.id
where o.status = '${@com.cf.imes.module.system.enums.pay.PayOrderStatusEnum@SUCCESS.status}'
<if test="reqVO.organId != null">
AND o.organ_id = #{reqVO.organId}
</if>
<if test="reqVO.productPrice != null">
AND p.total_amount = #{reqVO.productPrice}
</if>
<if test="reqVO.operator != null and reqVO.operator != ''">
AND o.creator = #{reqVO.operator}
</if>
<if test="reqVO.createTime != null and reqVO.createTime.length == 2">
AND o.create_time &gt;= #{reqVO.createTime[0]}
AND o.create_time &lt;= #{reqVO.createTime[1]}
</if>
order by o.id desc;
</select>
<select id="getRechargeTotalAmount" resultType="java.math.BigDecimal">
select sum(price) from pay_order
where status = '${@com.cf.imes.module.system.enums.pay.PayOrderStatusEnum@SUCCESS.status}' and deleted = false
</select>
</mapper>
@@ -23,4 +23,18 @@
#{id}
</foreach>
</select>
<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
from purchase_record;
</select>
<select id="getTotalRechargeUsageAmount" resultType="java.math.BigDecimal">
select sum(account_balance_spent)
from purchase_record
where deleted = false;
</select>
</mapper>
@@ -151,8 +151,8 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
*/
// 准备参数
OrganSaveReqVO reqVO = randomPojo(OrganSaveReqVO.class, o -> {
o.setContactName("晨丰");
o.setContactMobile("15601691300");
o.setOrgAdminName("晨丰");
o.setOrgAdminMobile("15601691300");
o.setPackageId(100L);
o.setStatus(randomCommonStatus());
o.setWebsite("https://www.cf.com");