diff --git a/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/DatavRestController.java b/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/DatavRestController.java index 5e7a77ac..3a27ee6c 100644 --- a/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/DatavRestController.java +++ b/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/DatavRestController.java @@ -1,10 +1,13 @@ package com.red.circle.console.adapter.app.user; -import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; +import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; import com.red.circle.console.app.dto.clientobject.datav.CountryDashboardCO; +import com.red.circle.console.app.dto.clientobject.datav.CountryDashboardRechargeDetailCO; import com.red.circle.console.app.dto.cmd.datav.CountryDashboardQryCmd; +import com.red.circle.console.app.dto.cmd.datav.CountryDashboardRechargeDetailQryCmd; import com.red.circle.console.app.service.app.datav.CountryDashboardService; import com.red.circle.console.app.service.app.user.DatavService; +import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.web.controller.BaseController; import com.red.circle.other.inner.model.cmd.user.OnlineCountQryCmd; import com.red.circle.other.inner.model.dto.user.ActiveUserCountryCodeDTO; @@ -50,4 +53,10 @@ public class DatavRestController extends BaseController { return countryDashboardService.query(cmd); } + @GetMapping("/country-dashboard/recharge-details") + public PageResult countryDashboardRechargeDetails( + CountryDashboardRechargeDetailQryCmd cmd) { + return countryDashboardService.pageRechargeDetails(cmd); + } + } diff --git a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardServiceImpl.java b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardServiceImpl.java index c68bc451..98dbdda5 100644 --- a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardServiceImpl.java +++ b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardServiceImpl.java @@ -2,11 +2,15 @@ package com.red.circle.console.app.service.app.datav; import com.red.circle.console.app.dto.clientobject.datav.CountryDashboardCO; import com.red.circle.console.app.dto.clientobject.datav.CountryDashboardMetricCO; +import com.red.circle.console.app.dto.clientobject.datav.CountryDashboardRechargeDetailCO; import com.red.circle.console.app.dto.cmd.datav.CountryDashboardQryCmd; +import com.red.circle.console.app.dto.cmd.datav.CountryDashboardRechargeDetailQryCmd; import com.red.circle.console.infra.database.rds.dao.datav.CountryDashboardDAO; import com.red.circle.console.infra.database.rds.dto.datav.CountryDashboardMetricDTO; +import com.red.circle.console.infra.database.rds.dto.datav.CountryDashboardRechargeDetailDTO; import com.red.circle.console.infra.database.rds.dto.datav.CountryDashboardRetentionUserDTO; import com.red.circle.console.infra.database.rds.dto.datav.CountryDashboardUserCountryDTO; +import com.red.circle.framework.dto.PageResult; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.Timestamp; @@ -69,6 +73,12 @@ public class CountryDashboardServiceImpl implements CountryDashboardService { mergeSql(rows, countryDashboardDAO.listOfficialRecharge( condition.periodType, condition.startTime, condition.endTime, condition.countryKeyword, condition.sysOrigin)); + mergeSql(rows, countryDashboardDAO.listMifapayRecharge( + condition.periodType, condition.startTime, condition.endTime, + condition.countryKeyword, condition.sysOrigin)); + mergeSql(rows, countryDashboardDAO.listGoogleRecharge( + condition.periodType, condition.startTime, condition.endTime, + condition.countryKeyword, condition.sysOrigin)); mergeSql(rows, countryDashboardDAO.listDealerRecharge( condition.periodType, condition.startTime, condition.endTime, condition.countryKeyword, condition.sysOrigin)); @@ -114,6 +124,51 @@ public class CountryDashboardServiceImpl implements CountryDashboardService { .setRecords(records); } + @Override + public PageResult pageRechargeDetails( + CountryDashboardRechargeDetailQryCmd cmd) { + QueryCondition condition = QueryCondition.of(cmd); + int cursor = Math.max(1, cmd == null || cmd.getCursor() == null ? 1 : cmd.getCursor()); + int limit = Math.max(1, cmd == null || cmd.getLimit() == null ? 100 : cmd.getLimit()); + limit = Math.min(100, limit); + int offset = (cursor - 1) * limit; + String countryCodes = normalizeCountryCodes(cmd == null ? null : cmd.getCountryCodes()); + + Long total = countryDashboardDAO.countRechargeDetails( + condition.startTime, condition.endTime, condition.countryKeyword, countryCodes, + condition.sysOrigin); + List records = countryDashboardDAO.listRechargeDetails( + condition.startTime, condition.endTime, condition.countryKeyword, countryCodes, + condition.sysOrigin, offset, limit) + .stream() + .map(this::toRechargeDetailCO) + .toList(); + + PageResult result = new PageResult<>(); + result.setCurrent(cursor); + result.setSize(limit); + result.setTotal(total == null ? 0L : total); + result.setRecords(records); + return result; + } + + private CountryDashboardRechargeDetailCO toRechargeDetailCO( + CountryDashboardRechargeDetailDTO dto) { + return new CountryDashboardRechargeDetailCO() + .setRecordId(dto.getRecordId()) + .setSourceType(dto.getSourceType()) + .setSourceChannel(dto.getSourceChannel()) + .setUserId(dto.getUserId()) + .setUserAccount(dto.getUserAccount()) + .setUserNickname(dto.getUserNickname()) + .setCountryCode(dto.getCountryCode()) + .setCountryName(dto.getCountryName()) + .setAmount(safe(dto.getAmount())) + .setCoinQuantity(safe(dto.getCoinQuantity())) + .setRemark(dto.getRemark()) + .setCreateTime(dto.getCreateTime()); + } + private void mergeSql(Map rows, List metrics) { if (metrics == null || metrics.isEmpty()) { @@ -125,6 +180,8 @@ public class CountryDashboardServiceImpl implements CountryDashboardService { row.setCountryNewUser(row.getCountryNewUser() + safeLong(metric.getCountryNewUser())); row.setNewUserRecharge(add(row.getNewUserRecharge(), metric.getNewUserRecharge())); row.setOfficialRecharge(add(row.getOfficialRecharge(), metric.getOfficialRecharge())); + row.setMifapayRecharge(add(row.getMifapayRecharge(), metric.getMifapayRecharge())); + row.setGoogleRecharge(add(row.getGoogleRecharge(), metric.getGoogleRecharge())); row.setDealerRecharge(add(row.getDealerRecharge(), metric.getDealerRecharge())); row.setSalaryExchange(add(row.getSalaryExchange(), metric.getSalaryExchange())); row.setLuckyGiftTotalFlow(add(row.getLuckyGiftTotalFlow(), metric.getLuckyGiftTotalFlow())); @@ -447,7 +504,8 @@ public class CountryDashboardServiceImpl implements CountryDashboardService { } private void calculateFormulaFields(CountryDashboardMetricCO row) { - row.setTotalRecharge(add(row.getOfficialRecharge(), row.getDealerRecharge())); + row.setTotalRecharge(add(add(row.getOfficialRecharge(), row.getMifapayRecharge()), + row.getDealerRecharge())); row.setLuckyGiftProfit(safe(row.getLuckyGiftTotalFlow()) .subtract(safe(row.getLuckyGiftPayout())) .subtract(safe(row.getLuckyGiftAnchorShare()))); @@ -474,6 +532,8 @@ public class CountryDashboardServiceImpl implements CountryDashboardService { total.setDailyActiveUser(total.getDailyActiveUser() + safeLong(row.getDailyActiveUser())); total.setNewUserRecharge(add(total.getNewUserRecharge(), row.getNewUserRecharge())); total.setOfficialRecharge(add(total.getOfficialRecharge(), row.getOfficialRecharge())); + total.setMifapayRecharge(add(total.getMifapayRecharge(), row.getMifapayRecharge())); + total.setGoogleRecharge(add(total.getGoogleRecharge(), row.getGoogleRecharge())); total.setDealerRecharge(add(total.getDealerRecharge(), row.getDealerRecharge())); total.setSalaryExchange(add(total.getSalaryExchange(), row.getSalaryExchange())); total.setGiftConsume(add(total.getGiftConsume(), row.getGiftConsume())); @@ -551,6 +611,18 @@ public class CountryDashboardServiceImpl implements CountryDashboardService { return value != null && !value.trim().isEmpty(); } + private static String normalizeCountryCodes(String value) { + if (!hasText(value)) { + return null; + } + String normalized = java.util.Arrays.stream(value.split(",")) + .map(String::trim) + .filter(CountryDashboardServiceImpl::hasText) + .distinct() + .collect(java.util.stream.Collectors.joining(",")); + return hasText(normalized) ? normalized : null; + } + private record MongoMetric(Long userId, String day, BigDecimal amount) { } diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clientobject/datav/CountryDashboardMetricCO.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clientobject/datav/CountryDashboardMetricCO.java index c6fc02cb..34880388 100644 --- a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clientobject/datav/CountryDashboardMetricCO.java +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clientobject/datav/CountryDashboardMetricCO.java @@ -32,6 +32,10 @@ public class CountryDashboardMetricCO implements Serializable { private BigDecimal dealerRecharge = BigDecimal.ZERO; + private BigDecimal mifapayRecharge = BigDecimal.ZERO; + + private BigDecimal googleRecharge = BigDecimal.ZERO; + private BigDecimal salaryExchange = BigDecimal.ZERO; private BigDecimal totalRecharge = BigDecimal.ZERO; diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clientobject/datav/CountryDashboardRechargeDetailCO.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clientobject/datav/CountryDashboardRechargeDetailCO.java new file mode 100644 index 00000000..6a10732b --- /dev/null +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clientobject/datav/CountryDashboardRechargeDetailCO.java @@ -0,0 +1,42 @@ +package com.red.circle.console.app.dto.clientobject.datav; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 国家数据大屏充值明细. + */ +@Data +@Accessors(chain = true) +public class CountryDashboardRechargeDetailCO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private String recordId; + + private String sourceType; + + private String sourceChannel; + + private Long userId; + + private String userAccount; + + private String userNickname; + + private String countryCode; + + private String countryName; + + private BigDecimal amount = BigDecimal.ZERO; + + private BigDecimal coinQuantity = BigDecimal.ZERO; + + private String remark; + + private String createTime; +} diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/datav/CountryDashboardRechargeDetailQryCmd.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/datav/CountryDashboardRechargeDetailQryCmd.java new file mode 100644 index 00000000..0e853222 --- /dev/null +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/datav/CountryDashboardRechargeDetailQryCmd.java @@ -0,0 +1,33 @@ +package com.red.circle.console.app.dto.cmd.datav; + +import java.io.Serial; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 国家数据大屏充值明细查询. + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class CountryDashboardRechargeDetailQryCmd extends CountryDashboardQryCmd { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 页码,从 1 开始. + */ + private Integer cursor; + + /** + * 每页条数. + */ + private Integer limit; + + /** + * 多个国家编码,逗号分隔. + */ + private String countryCodes; +} diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardService.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardService.java index 38d882cb..32576bbd 100644 --- a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardService.java +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardService.java @@ -1,7 +1,10 @@ package com.red.circle.console.app.service.app.datav; import com.red.circle.console.app.dto.clientobject.datav.CountryDashboardCO; +import com.red.circle.console.app.dto.clientobject.datav.CountryDashboardRechargeDetailCO; import com.red.circle.console.app.dto.cmd.datav.CountryDashboardQryCmd; +import com.red.circle.console.app.dto.cmd.datav.CountryDashboardRechargeDetailQryCmd; +import com.red.circle.framework.dto.PageResult; /** * 国家数据大屏. @@ -9,4 +12,7 @@ import com.red.circle.console.app.dto.cmd.datav.CountryDashboardQryCmd; public interface CountryDashboardService { CountryDashboardCO query(CountryDashboardQryCmd cmd); + + PageResult pageRechargeDetails( + CountryDashboardRechargeDetailQryCmd cmd); } diff --git a/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dao/datav/CountryDashboardDAO.java b/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dao/datav/CountryDashboardDAO.java index 7c23b72f..363447fd 100644 --- a/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dao/datav/CountryDashboardDAO.java +++ b/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dao/datav/CountryDashboardDAO.java @@ -1,6 +1,7 @@ package com.red.circle.console.infra.database.rds.dao.datav; import com.red.circle.console.infra.database.rds.dto.datav.CountryDashboardMetricDTO; +import com.red.circle.console.infra.database.rds.dto.datav.CountryDashboardRechargeDetailDTO; import com.red.circle.console.infra.database.rds.dto.datav.CountryDashboardRetentionUserDTO; import com.red.circle.console.infra.database.rds.dto.datav.CountryDashboardUserCountryDTO; import com.red.circle.console.infra.database.rds.entity.app.IUserBaseInfo; @@ -36,6 +37,20 @@ public interface CountryDashboardDAO extends BaseDAO { @Param("countryKeyword") String countryKeyword, @Param("sysOrigin") String sysOrigin); + List listMifapayRecharge( + @Param("periodType") String periodType, + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime, + @Param("countryKeyword") String countryKeyword, + @Param("sysOrigin") String sysOrigin); + + List listGoogleRecharge( + @Param("periodType") String periodType, + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime, + @Param("countryKeyword") String countryKeyword, + @Param("sysOrigin") String sysOrigin); + List listDealerRecharge( @Param("periodType") String periodType, @Param("startTime") LocalDateTime startTime, @@ -86,4 +101,20 @@ public interface CountryDashboardDAO extends BaseDAO { @Param("sysOrigin") String sysOrigin); List listUserCountryByIds(@Param("userIds") Collection userIds); + + Long countRechargeDetails( + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime, + @Param("countryKeyword") String countryKeyword, + @Param("countryCodes") String countryCodes, + @Param("sysOrigin") String sysOrigin); + + List listRechargeDetails( + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime, + @Param("countryKeyword") String countryKeyword, + @Param("countryCodes") String countryCodes, + @Param("sysOrigin") String sysOrigin, + @Param("offset") int offset, + @Param("limit") int limit); } diff --git a/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dto/datav/CountryDashboardMetricDTO.java b/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dto/datav/CountryDashboardMetricDTO.java index ac8cd41a..739112cc 100644 --- a/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dto/datav/CountryDashboardMetricDTO.java +++ b/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dto/datav/CountryDashboardMetricDTO.java @@ -25,6 +25,10 @@ public class CountryDashboardMetricDTO { private BigDecimal officialRecharge; + private BigDecimal mifapayRecharge; + + private BigDecimal googleRecharge; + private BigDecimal dealerRecharge; private BigDecimal salaryExchange; diff --git a/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dto/datav/CountryDashboardRechargeDetailDTO.java b/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dto/datav/CountryDashboardRechargeDetailDTO.java new file mode 100644 index 00000000..54577658 --- /dev/null +++ b/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/dto/datav/CountryDashboardRechargeDetailDTO.java @@ -0,0 +1,37 @@ +package com.red.circle.console.infra.database.rds.dto.datav; + +import java.math.BigDecimal; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 国家数据大屏充值明细 SQL 结果. + */ +@Data +@Accessors(chain = true) +public class CountryDashboardRechargeDetailDTO { + + private String recordId; + + private String sourceType; + + private String sourceChannel; + + private Long userId; + + private String userAccount; + + private String userNickname; + + private String countryCode; + + private String countryName; + + private BigDecimal amount; + + private BigDecimal coinQuantity; + + private String remark; + + private String createTime; +} diff --git a/rc-service/rc-service-console/console-infrastructure/src/main/resources/dao/datav/CountryDashboardDAO.xml b/rc-service/rc-service-console/console-infrastructure/src/main/resources/dao/datav/CountryDashboardDAO.xml index 2c9c936f..b4017f39 100644 --- a/rc-service/rc-service-console/console-infrastructure/src/main/resources/dao/datav/CountryDashboardDAO.xml +++ b/rc-service/rc-service-console/console-infrastructure/src/main/resources/dao/datav/CountryDashboardDAO.xml @@ -79,6 +79,65 @@ + + + AND FIND_IN_SET(u.country_code, #{countryCodes}) + + + + + SELECT + CONVERT(CAST(t.id AS CHAR) USING utf8mb4) COLLATE utf8mb4_unicode_ci AS recordId, + CONVERT('OFFICIAL' USING utf8mb4) COLLATE utf8mb4_unicode_ci AS sourceType, + CONVERT(IFNULL(t.pay_platform, '') USING utf8mb4) COLLATE utf8mb4_unicode_ci AS sourceChannel, + t.user_id AS userId, + IFNULL(t.unit_price, 0) AS amount, + CAST(NULL AS DECIMAL(20, 2)) AS coinQuantity, + CONVERT('' USING utf8mb4) COLLATE utf8mb4_unicode_ci AS remark, + t.create_time AS createTime + FROM order_purchase_history t + WHERE t.evn = 'PROD' + AND t.is_trial_period = 0 + AND t.status = 'COMPLETE' + AND t.pay_platform != 'MIFA_PAY' + + + UNION ALL + SELECT + CONVERT(CAST(t.id AS CHAR) USING utf8mb4) COLLATE utf8mb4_unicode_ci AS recordId, + CONVERT('MIFAPAY' USING utf8mb4) COLLATE utf8mb4_unicode_ci AS sourceType, + CONVERT(IFNULL(t.factory_code, '') USING utf8mb4) COLLATE utf8mb4_unicode_ci AS sourceChannel, + t.user_id AS userId, + IFNULL(t.compute_usd_amount, 0) AS amount, + CAST(NULL AS DECIMAL(20, 2)) AS coinQuantity, + CONVERT('' USING utf8mb4) COLLATE utf8mb4_unicode_ci AS remark, + t.create_time AS createTime + FROM order_user_purchase_pay t + WHERE t.evn = 'PROD' + AND t.factory_code = 'MIFA_PAY' + AND t.pay_status = 'SUCCESSFUL' + AND t.receipt_type = 'PAYMENT' + AND t.refund_status = 'NONE' + + + UNION ALL + SELECT + CONVERT(CAST(t.id AS CHAR) USING utf8mb4) COLLATE utf8mb4_unicode_ci AS recordId, + CONVERT('DEALER' USING utf8mb4) COLLATE utf8mb4_unicode_ci AS sourceType, + CONVERT(IFNULL(t.recharge_type, '') USING utf8mb4) COLLATE utf8mb4_unicode_ci AS sourceChannel, + t.user_id AS userId, + IFNULL(t.amount, 0) AS amount, + IFNULL(t.quantity, 0) AS coinQuantity, + CONVERT(IFNULL(t.remark, '') USING utf8mb4) COLLATE utf8mb4_unicode_ci AS remark, + t.create_time AS createTime + FROM likei_wallet.user_freight_balance_running_water t + WHERE t.origin = 'PURCHASE' + AND t.type = 0 + AND IFNULL(t.amount, 0) > 0 + + + + SELECT user_id, sys_origin, type, penny_amount, event_type, FROM_UNIXTIME(create_time / 1000) AS create_time FROM likei_wallet.wallet_gold_asset_record_1 @@ -201,6 +260,44 @@ WHERE t.evn = 'PROD' AND t.is_trial_period = 0 AND t.status = 'COMPLETE' + AND t.pay_platform != 'MIFA_PAY' + + + + GROUP BY countryCode, countryName, periodKey, periodName + + + + + + + + +