diff --git a/admin-ui/src/views/ai/balanceChangeRecord/index.vue b/admin-ui/src/views/ai/balanceChangeRecord/index.vue index 4a4b7c5..cfff618 100644 --- a/admin-ui/src/views/ai/balanceChangeRecord/index.vue +++ b/admin-ui/src/views/ai/balanceChangeRecord/index.vue @@ -69,12 +69,12 @@ - + @@ -93,11 +93,11 @@ - - + + - - + +
- + - + - - - - - - + + + + + + + { const allDeptList = response.data || [] this.deptOptions = allDeptList.filter(item => this.isSecondLevelDept(item)) }) }, - /** 判断是否为二级部门(一级部门的直属子部门) */ isSecondLevelDept(dept) { if (!dept || !dept.ancestors) { return false } return String(dept.ancestors).split(",").filter(Boolean).length === 2 }, - /** 查询团队每日消耗统计列表 */ - getList() { - if (!this.searched) { - this.loading = false - this.dataList = [] - this.total = 0 - return + syncDateRangeToQuery() { + if (Array.isArray(this.dateRange) && this.dateRange.length === 2) { + this.queryParams.startDate = this.dateRange[0] + this.queryParams.endDate = this.dateRange[1] + } else { + this.queryParams.startDate = null + this.queryParams.endDate = null } - this.loading = true - listData(this.queryParams).then(response => { - this.dataList = response.rows - this.total = response.total - this.loading = false - }) }, - /** 搜索按钮操作 */ + getList() { + this.syncDateRangeToQuery() + this.loading = true + listData(this.queryParams) + .then(response => { + this.dataList = response.rows + this.total = response.total + }) + .finally(() => { + this.loading = false + }) + }, handleQuery() { - if (!this.queryParams.statDate || !this.queryParams.deptId) { - this.$modal.msgWarning("请先填写日期和团队名称后再搜索") - return - } - this.searched = true this.queryParams.pageNum = 1 this.getList() }, - /** 重置按钮操作 */ resetQuery() { + this.initDefaultDateRange() this.resetForm("queryForm") - this.searched = false - this.loading = false - this.dataList = [] - this.total = 0 + this.queryParams.pageNum = 1 + this.syncDateRangeToQuery() + this.getList() } } } diff --git a/admin-ui/src/views/ai/groupchargeorder/index.vue b/admin-ui/src/views/ai/groupchargeorder/index.vue index c317ac8..fed8f2a 100644 --- a/admin-ui/src/views/ai/groupchargeorder/index.vue +++ b/admin-ui/src/views/ai/groupchargeorder/index.vue @@ -1,6 +1,6 @@ - - + + - - + + diff --git a/admin-ui/src/views/system/dept/index.vue b/admin-ui/src/views/system/dept/index.vue index 64734ef..d596436 100644 --- a/admin-ui/src/views/system/dept/index.vue +++ b/admin-ui/src/views/system/dept/index.vue @@ -22,11 +22,6 @@ 搜索 重置 - - - - - 展开/折叠 - - - + + + list = aiVideoReportDataService.selectTeamDailyConsumeList( - aiVideoReportData.getStatDate(), aiVideoReportData.getDeptId()); + public TableDataInfo list(@Valid @ModelAttribute GroupReportDataRequest query) { + List list = aiVideoReportDataService.selectTeamDailyConsumeList(query); return getDataTable(list); } @@ -51,9 +54,8 @@ public class AiVideoReportDataController extends BaseController @PreAuthorize("@ss.hasPermi('ai:data:export')") @Log(title = "AI视频生成统计数据,作为其他统计报的数据源", businessType = BusinessType.EXPORT) @PostMapping("/export") - public void export(HttpServletResponse response, AiVideoReportData aiVideoReportData) - { - List list = aiVideoReportDataService.selectAiVideoReportDataList(aiVideoReportData); + public void export(HttpServletResponse response, @Valid @RequestBody GroupReportDataRequest query) { + List list = aiVideoReportDataService.selectTeamDailyConsumeList(query); ExcelUtil util = new ExcelUtil(AiVideoReportData.class); util.exportExcel(response, list, "AI视频生成统计数据,作为其他统计报的数据源数据"); } @@ -63,19 +65,7 @@ public class AiVideoReportDataController extends BaseController */ @PreAuthorize("@ss.hasPermi('ai:data:query')") @GetMapping(value = "/{id}") - public AjaxResult getInfo(@PathVariable("id") Long id) - { + public AjaxResult getInfo(@PathVariable("id") Long id) { return success(aiVideoReportDataService.selectAiVideoReportDataById(id)); } - - /** - * 新增AI视频生成统计数据,作为其他统计报的数据源 - */ - @PreAuthorize("@ss.hasPermi('ai:data:add')") - @Log(title = "AI视频生成统计数据,作为其他统计报的数据源", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody AiVideoReportData aiVideoReportData) - { - return toAjax(aiVideoReportDataService.insertAiVideoReportData(aiVideoReportData)); - } } diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiBalanceChangeRecord.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiBalanceChangeRecord.java index d1602bf..fd1fda6 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiBalanceChangeRecord.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiBalanceChangeRecord.java @@ -57,15 +57,15 @@ public class AiBalanceChangeRecord extends BaseEntity { private Integer type; /** - * 变更金额 + * 变更积分 */ - @Excel(name = "变更金额") + @Excel(name = "变更积分") private BigDecimal changeAmount; /** * 变更后金额 */ - @Excel(name = "变更后金额") + @Excel(name = "变更后积分") private BigDecimal resultAmount; /** diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiGroupBalanceChangeRecord.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiGroupBalanceChangeRecord.java index ce6efe5..8b1c722 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiGroupBalanceChangeRecord.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiGroupBalanceChangeRecord.java @@ -52,12 +52,12 @@ public class AiGroupBalanceChangeRecord implements Serializable { @Excel(name = "操作类型", readConverterExp = "0=充值,1=退款,2=下发,3=回收,4=手动修改") private Integer type; - /** 变更金额 */ - @Excel(name = "变更金额") + /** 变更积分 */ + @Excel(name = "变更积分") private BigDecimal changeAmount; /** 变更后金额 */ - @Excel(name = "变更后金额") + @Excel(name = "变更后积分") private BigDecimal resultAmount; /** 备注(目前只作为手工修改时的备注) */ diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiOrder.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiOrder.java index 56f1482..f77b71d 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiOrder.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiOrder.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.core.domain.BaseEntity; import lombok.Data; +import lombok.EqualsAndHashCode; import java.math.BigDecimal; /** @@ -15,6 +16,7 @@ import java.math.BigDecimal; * @author shi * @date 2025-11-13 */ +@EqualsAndHashCode(callSuper = true) @Data @TableName("ai_order") public class AiOrder extends BaseEntity { diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiVideoReportData.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiVideoReportData.java index 497fd08..0ef31b1 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiVideoReportData.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiVideoReportData.java @@ -37,10 +37,6 @@ public class AiVideoReportData implements Serializable { @Excel(name = "部门ID") private Long deptId; - /** 用户ID(用户表主键) */ - @Excel(name = "用户ID") - private Long userId; - /** 消耗积分,按任务创建时间统计 */ @Excel(name = "消耗积分") private BigDecimal score; @@ -69,7 +65,7 @@ public class AiVideoReportData implements Serializable { @TableField(exist = false) private String deptName; - /** 查询日期 yyyyMMdd(非表字段) */ + /** 查询日期 yyyyMMdd(非表字段,子团队单日统计等仍可用) */ @TableField(exist = false) private String statDate; } \ No newline at end of file diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/request/GroupReportDataRequest.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/request/GroupReportDataRequest.java new file mode 100644 index 0000000..6c69a1f --- /dev/null +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/request/GroupReportDataRequest.java @@ -0,0 +1,22 @@ +package com.ruoyi.ai.domain.request; + +import java.io.Serializable; +import lombok.Data; + +/** + * 管理端「团队消耗统计」列表/导出查询条件(非表实体)。 + */ +@Data +public class GroupReportDataRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 统计开始日 yyyy-MM-dd(含) */ + private String startDate; + + /** 统计结束日 yyyy-MM-dd(含) */ + private String endDate; + + /** 二级团队部门 ID,可选;为空表示不限团队 */ + private Long deptId; +} diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/mapper/AiVideoReportDataMapper.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/mapper/AiVideoReportDataMapper.java index d198a03..d87f50d 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/mapper/AiVideoReportDataMapper.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/mapper/AiVideoReportDataMapper.java @@ -6,6 +6,7 @@ import java.math.BigDecimal; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.ai.domain.AiOrder; import com.ruoyi.ai.domain.AiVideoReportData; +import com.ruoyi.ai.domain.request.GroupReportDataRequest; import com.ruoyi.system.domain.subteam.SubteamVideoMetrics; import org.apache.ibatis.annotations.Param; @@ -17,14 +18,11 @@ import org.apache.ibatis.annotations.Param; */ public interface AiVideoReportDataMapper extends BaseMapper { /** - * 团队每日消耗统计查询(按天、团队聚合)。 + * 团队每日消耗统计查询(按日 date_key 前 8 位、团队聚合;区间内多日均返回一行一天一团队)。 * - * @param statDate 统计日期(yyyyMMdd) - * @param deptId 团队部门ID(精确匹配) - * @return 聚合结果 + * @param query 查询条件(startDate/endDate yyyy-MM-dd 或 yyyyMMdd、可选 deptId) */ - List selectTeamDailyConsumeList(@Param("statDate") String statDate, - @Param("deptId") Long deptId); + List selectTeamDailyConsumeList(GroupReportDataRequest query); /** * 按团队部门、日期聚合(团队后台消耗统计) @@ -39,35 +37,5 @@ public interface AiVideoReportDataMapper extends BaseMapper { @Param("startDay") String startDay, @Param("endDay") String endDay); - /** - * 按(date_key, dept_id, user_id)聚合累加视频消耗统计。 - * - * @param dateKey 小时Key(yyyyMMddHH) - * @param deptId 部门ID - * @param userId 用户ID - * @param score 消耗积分增量 - * @param orderCount 订单数增量 - * @param useTokens 三方tokens增量 - * @return 影响行数 - */ - int upsertVideoConsumeIncrement(@Param("dateKey") String dateKey, - @Param("deptId") Long deptId, - @Param("userId") Long userId, - @Param("score") BigDecimal score, - @Param("orderCount") Long orderCount, - @Param("useTokens") Long useTokens); - - /** - * 按(date_key, dept_id, user_id=0)聚合累加充值积分统计。 - * - * @param dateKey 小时Key(yyyyMMddHH) - * @param deptId 部门ID - * @param rechargeScore 充值积分增量 - * @return 影响行数 - */ - int upsertRechargeScoreIncrement(@Param("dateKey") String dateKey, - @Param("deptId") Long deptId, - @Param("rechargeScore") BigDecimal rechargeScore); - - void addNewOrderReportData(AiOrder aiOrder); + void insertOrUpdateData(AiVideoReportData record); } diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/IAiChargeRefundOrderService.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/IAiChargeRefundOrderService.java index 2c5b0e8..ee1d2bb 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/IAiChargeRefundOrderService.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/IAiChargeRefundOrderService.java @@ -29,14 +29,6 @@ public interface IAiChargeRefundOrderService { */ List selectAiChargeRefundOrderList(AiChargeRefundOrder aiChargeRefundOrder); - /** - * 分页查询团队(部门)充值退款订单列表 - * - * @param aiChargeRefundOrder 团队(部门)充值退款订单 - * @return 团队(部门)充值退款订单集合 - */ - IPage selectAiChargeRefundOrderPage(Page page, AiChargeRefundOrder aiChargeRefundOrder); - /** * 新增团队(部门)充值退款订单 * diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/IAiVideoReportDataService.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/IAiVideoReportDataService.java index 17cdd2f..88575cc 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/IAiVideoReportDataService.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/IAiVideoReportDataService.java @@ -3,9 +3,13 @@ package com.ruoyi.ai.service; import java.util.List; import java.math.BigDecimal; import java.util.Date; + +import com.ruoyi.ai.domain.AiChargeRefundOrder; +import com.ruoyi.ai.domain.AiOrder; import com.ruoyi.ai.domain.AiVideoReportData; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.ai.domain.request.GroupReportDataRequest; /** * AI视频生成统计数据,作为其他统计报的数据源Service接口 @@ -24,60 +28,16 @@ public interface IAiVideoReportDataService { AiVideoReportData selectAiVideoReportDataById(Long id); /** - * 查询AI视频生成统计数据,作为其他统计报的数据源列表 - * - * @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源 - * @return AI视频生成统计数据,作为其他统计报的数据源集合 + * 团队每日消耗统计查询(按日、团队聚合,支持日期区间与可选团队)。 */ - List selectAiVideoReportDataList(AiVideoReportData aiVideoReportData); - - /** - * 分页查询AI视频生成统计数据,作为其他统计报的数据源列表 - * - * @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源 - * @return AI视频生成统计数据,作为其他统计报的数据源集合 - */ - IPage selectAiVideoReportDataPage(Page page, AiVideoReportData aiVideoReportData); - - /** - * 新增AI视频生成统计数据,作为其他统计报的数据源 - * - * @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源 - * @return 结果 - */ - int insertAiVideoReportData(AiVideoReportData aiVideoReportData); - - /** - * 团队每日消耗统计查询(按天、团队聚合)。 - * - * @param statDate 统计日期(yyyyMMdd,必填) - * @param deptId 团队部门ID(必填,精确匹配) - * @return 聚合后的统计数据 - */ - List selectTeamDailyConsumeList(String statDate, Long deptId); + List selectTeamDailyConsumeList(GroupReportDataRequest query); /** * 团队每日消耗(按部门 ID,团队后台) */ List selectTeamDailyConsumeByDeptId(String statDate, Long deptId); - /** - * 按视频订单成功结果回写统计来源表(按小时、部门、账号聚合累加)。 - * - * @param createTime 任务创建时间 - * @param deptId 部门ID - * @param userId 账号ID - * @param score 消耗积分增量 - * @param useTokens 三方tokens增量 - */ - void syncVideoConsumeIncrement(Date createTime, Long deptId, Long userId, BigDecimal score, Long useTokens); + void updateReportDataWhenInsertAiOrder(AiOrder order); - /** - * 按充值/退款成功结果回写统计来源表(按小时、部门聚合累加)。 - * - * @param createTime 订单创建时间 - * @param deptId 部门ID - * @param rechargeScore 实际充值积分增量(充值为正,退款为负) - */ - void syncRechargeScoreIncrement(Date createTime, Long deptId, BigDecimal rechargeScore); + void updateReportDataWhenInsertChargeRefundOrder(AiChargeRefundOrder order); } diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiChargeRefundOrderServiceImpl.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiChargeRefundOrderServiceImpl.java index 9eeed17..098be73 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiChargeRefundOrderServiceImpl.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiChargeRefundOrderServiceImpl.java @@ -1,13 +1,14 @@ package com.ruoyi.ai.service.impl; -import java.util.List; -import java.math.BigDecimal; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.ai.domain.AiChargeRefundOrder; +import com.ruoyi.ai.mapper.AiChargeRefundOrderMapper; +import com.ruoyi.ai.service.IAiChargeRefundOrderService; +import com.ruoyi.ai.service.IAiVideoReportDataService; import com.ruoyi.common.enums.ChargeRefundOrderStatusType; -import com.ruoyi.common.enums.ChargeRefundOrderType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.SecurityUtils; @@ -15,10 +16,9 @@ import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.uuid.IdUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.ruoyi.ai.mapper.AiChargeRefundOrderMapper; -import com.ruoyi.ai.domain.AiChargeRefundOrder; -import com.ruoyi.ai.service.IAiVideoReportDataService; -import com.ruoyi.ai.service.IAiChargeRefundOrderService; + +import java.math.BigDecimal; +import java.util.List; /** * 团队(部门)充值退款订单Service业务层处理 @@ -57,22 +57,6 @@ public class AiChargeRefundOrderServiceImpl implements IAiChargeRefundOrderServi return aiChargeRefundOrderMapper.selectAiChargeRefundOrderList(aiChargeRefundOrder); } - /** - * 分页查询团队(部门)充值退款订单列表 - * - * @param aiChargeRefundOrder 团队(部门)充值退款订单 - * @return 团队(部门)充值退款订单 - */ - @Override - public IPage selectAiChargeRefundOrderPage(Page page, AiChargeRefundOrder aiChargeRefundOrder) { - if (aiChargeRefundOrder != null) { - aiChargeRefundOrder.setDeptName(null); - } - LambdaQueryWrapper query = Wrappers.lambdaQuery(aiChargeRefundOrder); - query.eq(AiChargeRefundOrder::getDelFlag, "0"); - return aiChargeRefundOrderMapper.selectPage(page, query); - } - /** * 新增团队(部门)充值退款订单 * @@ -81,7 +65,6 @@ public class AiChargeRefundOrderServiceImpl implements IAiChargeRefundOrderServi */ @Override public int insertAiChargeRefundOrder(AiChargeRefundOrder aiChargeRefundOrder) { - validateChargeAmount(aiChargeRefundOrder); if (StringUtils.isEmpty(aiChargeRefundOrder.getOrderNum())) { aiChargeRefundOrder.setOrderNum("CR" + IdUtils.fastSimpleUUID()); } @@ -92,47 +75,7 @@ public class AiChargeRefundOrderServiceImpl implements IAiChargeRefundOrderServi aiChargeRefundOrder.setCreateBy(SecurityUtils.getUserId()); aiChargeRefundOrder.setCreateTime(DateUtils.getNowDate()); int rows = aiChargeRefundOrderMapper.insert(aiChargeRefundOrder); - syncRechargeReportData(aiChargeRefundOrder); + aiVideoReportDataService.updateReportDataWhenInsertChargeRefundOrder(aiChargeRefundOrder); return rows; } - - /** - * 充值/退款单完成后,按“订单创建时间”同步到团队统计来源表。 - * - * @param order 充值退款订单 - */ - private void syncRechargeReportData(AiChargeRefundOrder order) { - if (order == null || order.getCreateTime() == null || order.getDeptId() == null) { - return; - } - if (order.getStatus() == null || order.getStatus() != ChargeRefundOrderStatusType.SUCCESS.getCode()) { - return; - } - if (order.getOrderType() == null || order.getAmount() == null) { - return; - } - BigDecimal rechargeScore; - int type = order.getOrderType().intValue(); - if (type == ChargeRefundOrderType.REFUND.getCode()) { - rechargeScore = order.getAmount().negate(); - } else { - rechargeScore = order.getAmount(); - } - aiVideoReportDataService.syncRechargeScoreIncrement(order.getCreateTime(), order.getDeptId(), rechargeScore); - } - - /** - * 充值、退款积分须为非负数。 - */ - private void validateChargeAmount(AiChargeRefundOrder o) { - if (o.getOrderType() == null || o.getAmount() == null) { - return; - } - int t = o.getOrderType().intValue(); - if (t == ChargeRefundOrderType.CHARGE.getCode() || t == ChargeRefundOrderType.REFUND.getCode()) { - if (o.getAmount().compareTo(BigDecimal.ZERO) < 0) { - throw new ServiceException("充值、退款类型的积分须填写非负数"); - } - } - } } diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiOrderServiceImpl.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiOrderServiceImpl.java index f232135..83b39b7 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiOrderServiceImpl.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiOrderServiceImpl.java @@ -8,7 +8,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.ai.domain.AiManager; import com.ruoyi.ai.domain.AiOrder; import com.ruoyi.ai.domain.AiStatistics; -import com.ruoyi.ai.domain.AiVideoReportData; import com.ruoyi.ai.mapper.AiOrderMapper; import com.ruoyi.ai.mapper.AiVideoReportDataMapper; import com.ruoyi.ai.service.*; @@ -33,7 +32,6 @@ import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; -import java.util.Locale; import java.util.UUID; /** @@ -251,7 +249,6 @@ public class AiOrderServiceImpl implements IAiOrderService { public void orderSuccess(AiOrder aiOrder) { aiOrder.setStatus(1); aiOrderMapper.updateById(aiOrder); - syncVideoReportData(aiOrder); AiStatistics aiStatistics = new AiStatistics(); aiStatistics.setSource(aiOrder.getSource()); aiStatistics.setGenerateCount(1L); @@ -259,7 +256,7 @@ public class AiOrderServiceImpl implements IAiOrderService { aiStatisticsService.saveOrUpdateData(aiStatistics); // 统计数据 - aiVideoReportDataMapper.addNewOrderReportData(aiOrder); + aiVideoReportDataService.updateReportDataWhenInsertAiOrder(aiOrder); } @Override @@ -360,18 +357,4 @@ public class AiOrderServiceImpl implements IAiOrderService { // BalanceChangerConstants.QUICK_VIDEO_GENERATION, TASK_SUCCESS_BALANCE_REMARK); return AjaxResult.success("callback success"); } - - /** - * 任务成功后按“提交时间”写入团队消耗统计来源表。 - * - * @param aiOrder 已成功订单 - */ - private void syncVideoReportData(AiOrder aiOrder) { - if (aiOrder == null || aiOrder.getCreateTime() == null || aiOrder.getDeptId() == null || aiOrder.getUserId() == null) { - return; - } - BigDecimal score = aiOrder.getAmount() != null ? aiOrder.getAmount() : BigDecimal.ZERO; - Long useTokens = aiOrder.getTotalUsage() != null ? aiOrder.getTotalUsage().longValue() : 0L; - aiVideoReportDataService.syncVideoConsumeIncrement(aiOrder.getCreateTime(), aiOrder.getDeptId(), aiOrder.getUserId(), score, useTokens); - } } diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiVideoReportDataServiceImpl.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiVideoReportDataServiceImpl.java index cf5bcd3..a5ad0a0 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiVideoReportDataServiceImpl.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiVideoReportDataServiceImpl.java @@ -1,14 +1,20 @@ package com.ruoyi.ai.service.impl; -import java.util.List; import java.math.BigDecimal; +import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.time.format.DateTimeFormatter; import java.util.Date; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.ruoyi.common.utils.DateUtils; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.ai.domain.AiChargeRefundOrder; +import com.ruoyi.ai.domain.AiOrder; +import com.ruoyi.ai.domain.request.GroupReportDataRequest; +import com.ruoyi.common.annotation.Excel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ruoyi.ai.mapper.AiVideoReportDataMapper; @@ -38,46 +44,9 @@ public class AiVideoReportDataServiceImpl implements IAiVideoReportDataService { return aiVideoReportDataMapper.selectById(id); } - /** - * 查询AI视频生成统计数据,作为其他统计报的数据源列表 - * - * @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源 - * @return AI视频生成统计数据,作为其他统计报的数据源 - */ @Override - public List selectAiVideoReportDataList(AiVideoReportData aiVideoReportData) { - LambdaQueryWrapper query = Wrappers.lambdaQuery(aiVideoReportData); - query.orderByDesc(AiVideoReportData::getId); - return aiVideoReportDataMapper.selectList(query); - } - - /** - * 分页查询AI视频生成统计数据,作为其他统计报的数据源列表 - * - * @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源 - * @return AI视频生成统计数据,作为其他统计报的数据源 - */ - @Override - public IPage selectAiVideoReportDataPage(Page page, AiVideoReportData aiVideoReportData) { - LambdaQueryWrapper query = Wrappers.lambdaQuery(aiVideoReportData); - return aiVideoReportDataMapper.selectPage(page, query); - } - - /** - * 新增AI视频生成统计数据,作为其他统计报的数据源 - * - * @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源 - * @return 结果 - */ - @Override - public int insertAiVideoReportData(AiVideoReportData aiVideoReportData) { - aiVideoReportData.setCreateTime(DateUtils.getNowDate()); - return aiVideoReportDataMapper.insert(aiVideoReportData); - } - - @Override - public List selectTeamDailyConsumeList(String statDate, Long deptId) { - return aiVideoReportDataMapper.selectTeamDailyConsumeList(statDate, deptId); + public List selectTeamDailyConsumeList(GroupReportDataRequest query) { + return aiVideoReportDataMapper.selectTeamDailyConsumeList(query); } @Override @@ -86,20 +55,24 @@ public class AiVideoReportDataServiceImpl implements IAiVideoReportDataService { } @Override - public void syncVideoConsumeIncrement(Date createTime, Long deptId, Long userId, BigDecimal score, Long useTokens) { - if (createTime == null || deptId == null || userId == null || score == null || useTokens == null) { - return; - } - String dateKey = new SimpleDateFormat("yyyyMMddHH").format(createTime); - aiVideoReportDataMapper.upsertVideoConsumeIncrement(dateKey, deptId, userId, score, 1L, useTokens); + public void updateReportDataWhenInsertAiOrder(AiOrder order) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH"); + AiVideoReportData record = new AiVideoReportData(); + record.setDateKey(sdf.format(order.getCreateTime())); + record.setDeptId(order.getDeptId()); + record.setScore(order.getAmount()); + record.setOrderCount(1L); + record.setUseTokens(order.getTotalUsage().longValue()); + aiVideoReportDataMapper.insertOrUpdateData(record); } @Override - public void syncRechargeScoreIncrement(Date createTime, Long deptId, BigDecimal rechargeScore) { - if (createTime == null || deptId == null || rechargeScore == null) { - return; - } - String dateKey = new SimpleDateFormat("yyyyMMddHH").format(createTime); - aiVideoReportDataMapper.upsertRechargeScoreIncrement(dateKey, deptId, rechargeScore); + public void updateReportDataWhenInsertChargeRefundOrder(AiChargeRefundOrder order) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH"); + AiVideoReportData record = new AiVideoReportData(); + record.setDateKey(sdf.format(order.getCreateTime())); + record.setDeptId(order.getDeptId()); + record.setRechargeScore(order.getAmount()); + aiVideoReportDataMapper.insertOrUpdateData(record); } } diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/DeptChargeRefundServiceImpl.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/DeptChargeRefundServiceImpl.java index 4fc8198..969b6cc 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/DeptChargeRefundServiceImpl.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/DeptChargeRefundServiceImpl.java @@ -50,9 +50,10 @@ public class DeptChargeRefundServiceImpl implements IDeptChargeRefundService { if (orderType == null) { throw new ServiceException("订单类型不合法"); } + if (request.getAmount() <= 0) { + throw new ServiceException("积分须是大于0的正整数"); + } - // 积分变动量:与 sys_dept.balance 增减一致;money 仅落库订单,不参与此处运算 - BigDecimal amountBd = BigDecimal.valueOf(request.getAmount()); String orderNum = buildOrderNum(); Date now = DateUtils.getNowDate(); @@ -65,9 +66,17 @@ public class DeptChargeRefundServiceImpl implements IDeptChargeRefundService { order.setOrderNum(orderNum); order.setDeptId(request.getDeptId()); order.setOrderType(request.getOrderType()); - // 金额两位小数:向零截断(非四舍五入),避免入账金额被抬高 - order.setMoney(request.getMoney().setScale(2, RoundingMode.DOWN)); - order.setAmount(amountBd); + // 金额两位小数 + BigDecimal money = request.getMoney().setScale(2, RoundingMode.DOWN); + // 积分变动量 + BigDecimal amount = BigDecimal.valueOf(request.getAmount()); + // 退款变小数 + if (order.getOrderType() == ChargeRefundOrderType.REFUND.getCode()) { + money = money.negate(); + amount = amount.negate(); + } + order.setMoney(money); + order.setAmount(amount); order.setRemark(request.getRemark()); order.setStatus(ChargeRefundOrderStatusType.SUCCESS.getCode()); @@ -76,9 +85,9 @@ public class DeptChargeRefundServiceImpl implements IDeptChargeRefundService { // 2) 原子更新部门积分;退款时 rows==0 表示余额不足或部门无效,依赖事务回滚撤销上一 INSERT int rows; if (orderType == ChargeRefundOrderType.CHARGE) { - rows = deptService.addDeptBalance(request.getDeptId(), amountBd); + rows = deptService.addDeptBalance(request.getDeptId(), amount.abs()); } else { - rows = deptService.subtractDeptBalance(request.getDeptId(), amountBd); + rows = deptService.subtractDeptBalance(request.getDeptId(), amount.abs()); } if (rows == 0) { if (orderType == ChargeRefundOrderType.REFUND) { @@ -93,17 +102,13 @@ public class DeptChargeRefundServiceImpl implements IDeptChargeRefundService { } // 3) 流水:充值为正、退款为负;result_amount 为变动后部门余额 - BigDecimal signedChange = orderType == ChargeRefundOrderType.CHARGE - ? amountBd - : amountBd.negate(); - AiGroupBalanceChangeRecord record = new AiGroupBalanceChangeRecord(); record.setRelationOrderNo(orderNum); record.setDeptId(request.getDeptId()); record.setType(orderType == ChargeRefundOrderType.CHARGE ? GroupBalanceChangeType.RECHARGE.getCode() : GroupBalanceChangeType.REFUND.getCode()); - record.setChangeAmount(signedChange); + record.setChangeAmount(amount); record.setResultAmount(dept.getBalance()); record.setRemark(request.getRemark()); record.setCreateTime(now); diff --git a/web-api/ruoyi-system/src/main/resources/mapper/ai/AiVideoReportDataMapper.xml b/web-api/ruoyi-system/src/main/resources/mapper/ai/AiVideoReportDataMapper.xml index 1764a4b..54240fd 100644 --- a/web-api/ruoyi-system/src/main/resources/mapper/ai/AiVideoReportDataMapper.xml +++ b/web-api/ruoyi-system/src/main/resources/mapper/ai/AiVideoReportDataMapper.xml @@ -8,7 +8,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - @@ -19,79 +18,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select id, date_key, dept_id, user_id, score, recharge_score, order_count, use_tokens, create_time, update_time from ai_video_report_data + select id, date_key, dept_id, score, recharge_score, order_count, use_tokens, create_time, update_time from ai_video_report_data - - - - insert into ai_video_report_data - - date_key, - dept_id, - user_id, - score, - order_count, - use_tokens, - recharge_score, - create_time, - update_time, - - - #{dateKey}, - #{deptId}, - #{userId}, - #{score}, - #{orderCount}, - #{useTokens}, - #{rechargeScore}, - #{createTime}, - #{updateTime}, - - - - + select substr(vrd.date_key, 1, 10) as date_key, vrd.dept_id, d.dept_name, sum(vrd.recharge_score) as recharge_score, + sum(vrd.score) as score, sum(vrd.order_count) as order_count, sum(vrd.use_tokens) as use_tokens + from ai_video_report_data vrd left join sys_dept d on d.dept_id = vrd.dept_id - - and vrd.date_key like concat(#{statDate}, '%') + + and substr(vrd.date_key, 1, 10) >= #{startDate} + + + and substr(vrd.date_key, 1, 10) <= #{endDate} and vrd.dept_id = #{deptId} - group by substr(vrd.date_key, 1, 8), vrd.dept_id, d.dept_name - order by substr(vrd.date_key, 1, 8) desc, vrd.dept_id desc + group by substr(vrd.date_key, 1, 10), vrd.dept_id, d.dept_name + order by substr(vrd.date_key, 1, 10) desc, vrd.dept_id desc