|
@@ -12,13 +12,20 @@ import org.nutz.dao.Dao;
|
|
|
import org.nutz.dao.Sqls;
|
|
|
import org.nutz.dao.sql.Criteria;
|
|
|
import org.nutz.dao.sql.Sql;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.beans.BeanWrapper;
|
|
|
+import org.springframework.beans.BeanWrapperImpl;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import java.beans.PropertyDescriptor;
|
|
|
import java.math.BigDecimal;
|
|
|
-import java.math.BigInteger;
|
|
|
+import java.math.RoundingMode;
|
|
|
import java.time.LocalDate;
|
|
|
+import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.Set;
|
|
|
|
|
|
/**
|
|
|
* @author tianhua
|
|
@@ -35,93 +42,102 @@ public class AdsOverallSummaryServiceImpl implements IAdsOverallSummaryService {
|
|
|
@Override
|
|
|
public AdsOverallSummaryVO getOverallSummaryData(AdsOverallSummaryParam param) {
|
|
|
|
|
|
- //前端展示数据的实体对象
|
|
|
- AdsOverallSummaryVO adsOverallSummaryVO = new AdsOverallSummaryVO();
|
|
|
//获取查询条件 整体数据查询 不需要日期
|
|
|
- Condition totalDataCon = myCondition(param, false, false);
|
|
|
+ Condition totalDataCon = myCondition(param, false, -1);
|
|
|
+ //查询条件转换为sql语句 设置映射 Entity为 AdsOverallSummary对象
|
|
|
+ String totalDataConString = totalDataCon.toSql(dao.getEntity(AdsOverallSummary.class));
|
|
|
+ //自定义sql语句
|
|
|
+ Sql totalDataSql = Sqls.create("SELECT \n" +
|
|
|
+ "SUM(x.today_player_count) total_players ,\n" +
|
|
|
+ "SUM(x.today_total_cost) total_cost ,\n" +
|
|
|
+ "SUM(x.today_amount) total_amount ,\n" +
|
|
|
+ "SUM(x.today_agent_count) total_agent_count ,\n" +
|
|
|
+ "SUM(x.today_game_count) total_game_count ,\n" +
|
|
|
+ "SUM(x.today_new_player_amount)/SUM(x.today_total_cost) total_roi \n" +
|
|
|
+ "FROM ads_overall_summary x " + totalDataConString);
|
|
|
+
|
|
|
+ //自定义回显对象 结果自动封装到给定的Entity对象中
|
|
|
+ totalDataSql.setCallback(Sqls.callback.entity());
|
|
|
+ totalDataSql.setEntity(dao.getEntity(AdsOverallSummaryVO.class));
|
|
|
+ //执行自定义sql语句
|
|
|
+ dao.execute(totalDataSql);
|
|
|
+ //得到一个包含有总数据的AdsOverallSummaryVO对象
|
|
|
+ AdsOverallSummaryVO totalDataVO = totalDataSql.getObject(AdsOverallSummaryVO.class);
|
|
|
+
|
|
|
+
|
|
|
//获取查询条件 查询今日数据 需要按当前日期查询
|
|
|
- Condition todayDataCon = myCondition(param, false, true);
|
|
|
-
|
|
|
- //查询数据 设置到实体类中
|
|
|
- //总玩家数
|
|
|
- adsOverallSummaryVO.setTotalPlayers(BigInteger.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayPlayerCount", totalDataCon)));
|
|
|
- //今日新增玩家数
|
|
|
- adsOverallSummaryVO.setTodayPlayerCount(BigInteger.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayPlayerCount", todayDataCon)));
|
|
|
- //昨日新增玩家数
|
|
|
- adsOverallSummaryVO.setYesterdayPlayerCount(BigInteger.valueOf(dao.func(AdsOverallSummary.class, "sum", "yesterdayPlayerCount", todayDataCon)));
|
|
|
-
|
|
|
- //累计消耗
|
|
|
- adsOverallSummaryVO.setTotalCost(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayTotalCost", totalDataCon)));
|
|
|
- //今日消耗
|
|
|
- adsOverallSummaryVO.setTodayTotalCost(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayTotalCost", todayDataCon)));
|
|
|
- //昨日消耗
|
|
|
- adsOverallSummaryVO.setYesterdayTotalCost(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "yesterdayTotalCost", todayDataCon)));
|
|
|
-
|
|
|
- //累计充值
|
|
|
- adsOverallSummaryVO.setTotalAmount(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayAmount", totalDataCon)));
|
|
|
- //今日新用户充值
|
|
|
- adsOverallSummaryVO.setTodayNewPlayerAmount(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayNewPlayerAmount", todayDataCon)));
|
|
|
- //今日账面充值
|
|
|
- adsOverallSummaryVO.setTodayAmount(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayAmount", todayDataCon)));
|
|
|
- //昨日新用户充值
|
|
|
- adsOverallSummaryVO.setYesterdayNewPlayerAmount(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "yesterdayNewPlayerAmount", todayDataCon)));
|
|
|
- //昨日账面充值
|
|
|
- adsOverallSummaryVO.setYesterdayAmount(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "yesterdayAmount", todayDataCon)));
|
|
|
-
|
|
|
- //总渠道数量
|
|
|
- adsOverallSummaryVO.setTotalAgentCount(BigInteger.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayAgentCount", totalDataCon)));
|
|
|
- //今日新增渠道数量
|
|
|
- adsOverallSummaryVO.setTodayAgentCount(BigInteger.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayAgentCount", todayDataCon)));
|
|
|
- //昨日新增渠道数量
|
|
|
- adsOverallSummaryVO.setYesterdayAgentCount(BigInteger.valueOf(dao.func(AdsOverallSummary.class, "sum", "yesterdayAgentCount", todayDataCon)));
|
|
|
-
|
|
|
- //游戏总计数量
|
|
|
- adsOverallSummaryVO.setTotalGameCount(BigInteger.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayGameCount", totalDataCon)));
|
|
|
- //今日新增游戏数量
|
|
|
- adsOverallSummaryVO.setTodayGameCount(BigInteger.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayGameCount", todayDataCon)));
|
|
|
- //昨日新增游戏数量
|
|
|
- adsOverallSummaryVO.setYesterdayGameCount(BigInteger.valueOf(dao.func(AdsOverallSummary.class, "sum", "yesterdayGameCount", todayDataCon)));
|
|
|
-
|
|
|
- //总回本率
|
|
|
- adsOverallSummaryVO.setTotalRoi(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "totalRoi", totalDataCon)));
|
|
|
- //首日回本率
|
|
|
- adsOverallSummaryVO.setFirstRoi(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "firstRoi", totalDataCon)));
|
|
|
- //7天回本率
|
|
|
- adsOverallSummaryVO.setD7TotalRoi(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "d7TotalRoi", totalDataCon)));
|
|
|
- //30天回本率
|
|
|
- adsOverallSummaryVO.setD30TotalRoi(BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "d30TotalRoi", totalDataCon)));
|
|
|
-
|
|
|
- return adsOverallSummaryVO;
|
|
|
+ Condition todayDataCon = myCondition(param, false, 1);
|
|
|
+ //查询条件转换为sql语句 设置映射 Entity为 AdsOverallSummary对象
|
|
|
+ String todayDataConString = todayDataCon.toSql(dao.getEntity(AdsOverallSummary.class));
|
|
|
+ Sql todayDataSql = Sqls.create("SELECT \n" +
|
|
|
+ "SUM(x.today_player_count) today_player_count ,\n" +
|
|
|
+ "SUM(x.yesterday_player_count) yesterday_player_count ,\n" +
|
|
|
+ "SUM(x.today_total_cost) today_total_cost ,\n" +
|
|
|
+ "SUM(x.yesterday_total_cost) yesterday_total_cost ,\n" +
|
|
|
+ "SUM(x.today_new_player_amount) today_new_player_amount ,\n" +
|
|
|
+ "SUM(x.today_amount) today_amount ,\n" +
|
|
|
+ "SUM(x.yesterday_new_player_amount) yesterday_new_player_amount ,\n" +
|
|
|
+ "SUM(x.yesterday_amount) yesterday_amount ,\n" +
|
|
|
+ "SUM(x.today_agent_count) today_agent_count ,\n" +
|
|
|
+ "SUM(x.yesterday_agent_count) yesterday_agent_count ,\n" +
|
|
|
+ "SUM(x.today_game_count) today_game_count ,\n" +
|
|
|
+ "SUM(x.yesterday_game_count) yesterday_game_count ,\n" +
|
|
|
+ "SUM(x.first_new_user_amount)/SUM(x.today_total_cost) first_roi \n" +
|
|
|
+ "FROM ads_overall_summary x" + todayDataConString);
|
|
|
+
|
|
|
+ //自定义回显对象 结果自动封装到给定的Entity对象中
|
|
|
+ todayDataSql.setCallback(Sqls.callback.entity());
|
|
|
+ todayDataSql.setEntity(dao.getEntity(AdsOverallSummaryVO.class));
|
|
|
+ //执行自定义sql语句
|
|
|
+ dao.execute(todayDataSql);
|
|
|
+ //得到一个包含有今日和昨日数据的AdsOverallSummaryVO对象
|
|
|
+ AdsOverallSummaryVO todayDataVO = todayDataSql.getObject(AdsOverallSummaryVO.class);
|
|
|
+
|
|
|
+ //拼接参数
|
|
|
+ copyNullProperties(totalDataVO, todayDataVO);
|
|
|
+
|
|
|
+ //7日和30日Roi数据需要手动计算
|
|
|
+ //7日内新用户累计充值
|
|
|
+ BigDecimal d7NewPlayerAmount = BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayNewPlayerAmount", myCondition(param, false, 7)));
|
|
|
+ //7日内总消耗
|
|
|
+ BigDecimal d7TotalCost = BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayTotalCost", myCondition(param, false, 7)));
|
|
|
+ //计算7日Roi
|
|
|
+ todayDataVO.setD7TotalRoi(d7NewPlayerAmount.divide(d7TotalCost, 4, RoundingMode.HALF_UP));
|
|
|
+
|
|
|
+ //30日内新用户累计充值
|
|
|
+ BigDecimal d30NewPlayerAmount = BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayNewPlayerAmount", myCondition(param, false, 30)));
|
|
|
+ //30日内总消耗
|
|
|
+ BigDecimal d30TotalCost = BigDecimal.valueOf(dao.func(AdsOverallSummary.class, "sum", "todayTotalCost", myCondition(param, false, 30)));
|
|
|
+ //计算30日Roi
|
|
|
+ todayDataVO.setD30TotalRoi(d30NewPlayerAmount.divide(d30TotalCost, 4, RoundingMode.HALF_UP));
|
|
|
+
|
|
|
+ //存在首日Roi为null的情况 消耗为0 但是有用户充值 无法计算 设置为 0
|
|
|
+ if (todayDataVO.getFirstRoi() == null) {
|
|
|
+ todayDataVO.setFirstRoi(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+
|
|
|
+ return todayDataVO;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public List<AdsOverallSummaryLineDataVO> getOverallSummaryLineData(AdsOverallSummaryParam param) {
|
|
|
|
|
|
- //前端展示的折线数据对象实体
|
|
|
- AdsOverallSummaryLineDataVO adsOverallSummaryLineDataVO = new AdsOverallSummaryLineDataVO();
|
|
|
-
|
|
|
//根据条件获取数据
|
|
|
- Condition lineCon = myCondition(param, true, false);
|
|
|
+ Condition lineCon = myCondition(param, true, -1);
|
|
|
//查询条件变为字符串
|
|
|
- String s = lineCon.toSql(dao.getEntity(AdsOverallSummary.class));
|
|
|
+ String lineConString = lineCon.toSql(dao.getEntity(AdsOverallSummary.class));
|
|
|
|
|
|
- //自定义sql语句
|
|
|
+ //自定义sql语句 加上条件字符串
|
|
|
Sql sql = Sqls.create("Select dt," +
|
|
|
"SUM(x.today_total_cost) cost, " +
|
|
|
- "SUM(x.today_buy_amount)+SUM(x.today_nature_amount) amount," +
|
|
|
+ "SUM(x.today_amount) amount, " +
|
|
|
"SUM(x.today_buy_amount) buy_amount," +
|
|
|
"SUM(x.today_nature_amount) nature_amount, " +
|
|
|
- "SUM(x.first_roi) first_roi," +
|
|
|
+ "SUM(x.first_new_user_amount)/SUM(x.today_total_cost) first_roi," +
|
|
|
"SUM(x.today_player_count) player_account " +
|
|
|
- "from ads_overall_summary x " + s);
|
|
|
-
|
|
|
- //拼接查询条件
|
|
|
- //sql.setCondition(lineCon);
|
|
|
-
|
|
|
-
|
|
|
- log.info("sql:" + sql.toString());
|
|
|
+ "from ads_overall_summary x " + lineConString);
|
|
|
|
|
|
- //自定义回显对象
|
|
|
+ //自定义回显对象 结果自动添加到一个List中 List<Entity>
|
|
|
sql.setCallback(Sqls.callback.entities());
|
|
|
sql.setEntity(dao.getEntity(AdsOverallSummaryLineDataVO.class));
|
|
|
|
|
@@ -131,16 +147,15 @@ public class AdsOverallSummaryServiceImpl implements IAdsOverallSummaryService {
|
|
|
return sql.getList(AdsOverallSummaryLineDataVO.class);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* 自定义查询条件
|
|
|
*
|
|
|
- * @param param 前端传递的查询参数实体
|
|
|
- * @param needLocalDate 是否拼接日期查询条件
|
|
|
- * @param isQueryTodayData 是否是查询今日数据
|
|
|
+ * @param param 前端传递的查询参数实体
|
|
|
+ * @param needLocalDate 是否拼接日期查询条件
|
|
|
+ * @param queryDays 拼接需要查询数据的天数条件(给今日昨日、首日Roi、7日Roi以及30日Roi使用)
|
|
|
* @return Condition
|
|
|
*/
|
|
|
- private Condition myCondition(AdsOverallSummaryParam param, Boolean needLocalDate, Boolean isQueryTodayData) {
|
|
|
+ private Condition myCondition(AdsOverallSummaryParam param, Boolean needLocalDate, Integer queryDays) {
|
|
|
|
|
|
Criteria cri = Cnd.cri();
|
|
|
//默认查询条件
|
|
@@ -161,9 +176,22 @@ public class AdsOverallSummaryServiceImpl implements IAdsOverallSummaryService {
|
|
|
cri.where().andEquals("accountId", param.getAccountId());
|
|
|
}
|
|
|
|
|
|
- //如果需要查询今日及昨日数据 就指定查询日期条件为当天日期
|
|
|
- if (isQueryTodayData) {
|
|
|
- cri.where().andEquals("dt", LocalDate.now());
|
|
|
+ //根据参数拼接条件
|
|
|
+ switch (queryDays) {
|
|
|
+ case 1:
|
|
|
+ cri.where().andEquals("dt", LocalDate.now());
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 7:
|
|
|
+ cri.where().andBetween("dt", LocalDate.now().minusDays(7), LocalDate.now());
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 30:
|
|
|
+ cri.where().andBetween("dt", LocalDate.now().minusDays(30), LocalDate.now());
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
//折线数据需要拼接时间查询条件
|
|
@@ -173,15 +201,50 @@ public class AdsOverallSummaryServiceImpl implements IAdsOverallSummaryService {
|
|
|
cri.where().andBetween("dt", param.getBeginDate(), param.getEndDate());
|
|
|
//日期排序
|
|
|
} else {
|
|
|
- //没有具体时间默认查询今天数据
|
|
|
+ //没有具体时间默认查询至今30日的数据
|
|
|
cri.where().andBetween("dt", LocalDate.now().minusDays(30), LocalDate.now());
|
|
|
}
|
|
|
//按日期分组
|
|
|
- cri.getGroupBy().groupBy("dt").asc("dt");
|
|
|
+ cri.getGroupBy().groupBy("dt");
|
|
|
+ //按日期排序 升序
|
|
|
+ cri.getOrderBy().asc("dt");
|
|
|
}
|
|
|
|
|
|
return cri;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 所有为空值的属性都不copy
|
|
|
+ *
|
|
|
+ * @param source
|
|
|
+ * @param target
|
|
|
+ */
|
|
|
+ public static void copyNullProperties(Object source, Object target) {
|
|
|
+ BeanUtils.copyProperties(source, target, getNullField(source));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取属性中为空的字段
|
|
|
+ *
|
|
|
+ * @param target
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static String[] getNullField(Object target) {
|
|
|
+ BeanWrapper beanWrapper = new BeanWrapperImpl(target);
|
|
|
+ PropertyDescriptor[] propertyDescriptors = beanWrapper.getPropertyDescriptors();
|
|
|
+ Set<String> notNullFieldSet = new HashSet<>();
|
|
|
+ if (propertyDescriptors.length > 0) {
|
|
|
+ for (PropertyDescriptor p : propertyDescriptors) {
|
|
|
+ String name = p.getName();
|
|
|
+ Object value = beanWrapper.getPropertyValue(name);
|
|
|
+ if (Objects.isNull(value)) {
|
|
|
+ notNullFieldSet.add(name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String[] notNullField = new String[notNullFieldSet.size()];
|
|
|
+ return notNullFieldSet.toArray(notNullField);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
}
|