Browse Source

设备主收入数据聚合

master
nili 8 months ago
parent
commit
cd7e0bc069
  1. 21
      game-dao/src/main/java/awesome/group/game/dao/bean/MatrixAdvAggregationSub.java
  2. 17
      game-dao/src/main/java/awesome/group/game/dao/mapper/MatrixAdvAggregationSubMapper.java
  3. 185
      game-service/src/main/java/awesome/group/game/service/AdminDeviceService.java
  4. 2
      game-service/src/main/java/awesome/group/game/service/AdminService.java
  5. 34
      game-service/src/main/java/awesome/group/game/service/AggregationSubService.java
  6. 9
      game-service/src/test/java/awesome/group/game/service/AdminServiceTest.java
  7. 22
      game-web/src/main/java/awesome/group/game/web/rest/matrix/DeviceController.java

21
game-dao/src/main/java/awesome/group/game/dao/bean/MatrixAdvAggregationSub.java

@ -0,0 +1,21 @@
package awesome.group.game.dao.bean;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.sql.Timestamp;
@Data
public class MatrixAdvAggregationSub {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private Integer appId;
private Integer adminId;
private Integer date;
private Integer platform;//1穿山甲,2腾讯,3百度联盟,4 Mintegral,5 快手,6游可赢,7 Sigmob,8 Admob
private Long income;//ecpm, 单位:分
private Long incomeReal;//抽成后ecpm,单位:分
private Integer incomeRate;//单位:分
private Timestamp createdAt;
}

17
game-dao/src/main/java/awesome/group/game/dao/mapper/MatrixAdvAggregationSubMapper.java

@ -0,0 +1,17 @@
package awesome.group.game.dao.mapper;
import awesome.group.game.dao.bean.MatrixAdvAggregationSub;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Insert;
import java.util.List;
public interface MatrixAdvAggregationSubMapper extends BaseMapper<MatrixAdvAggregationSub> {
@Insert("<script>" +
"insert ignore into matrix_adv_aggregation_sub(app_id, admin_id, date, platform, income, income_real, income_rate) values " +
"<foreach item = 'd' index = 'index' collection = 'data' separator =',' >" +
"(#{d.appId}, #{d.adminId}, #{d.date}, #{d.platform}, #{d.income}, #{d.incomeReal}, #{d.incomeRate})" +
"</foreach>" +
"</script>")
int insertBatch(List<MatrixAdvAggregationSub> data);
}

185
game-service/src/main/java/awesome/group/game/service/AdminDeviceService.java

@ -1,19 +1,29 @@
package awesome.group.game.service;
import awesome.group.game.dao.bean.MatrixAdmin;
import awesome.group.game.dao.bean.MatrixAdminDevice;
import awesome.group.game.dao.bean.MatrixApp;
import awesome.group.game.dao.mapper.MatrixAdminDeviceMapper;
import awesome.group.game.dao.mapper.MatrixAdminMapper;
import awesome.group.game.dao.mapper.MatrixAppMapper;
import awesome.group.game.dao.bean.*;
import awesome.group.game.dao.mapper.*;
import awesome.group.game.service.bo.DateIncome;
import awesome.group.game.service.bo.IncomeQuery;
import awesome.group.game.service.bo.OverviewBo;
import awesome.group.game.service.common.exception.PaganiException;
import awesome.group.game.service.common.exception.PaganiExceptionCode;
import awesome.group.game.service.util.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class AdminDeviceService {
@ -29,6 +39,18 @@ public class AdminDeviceService {
@Autowired
private MatrixAppMapper appMapper;
@Autowired
private MatrixAdvAggregationSubMapper subMapper;
@Autowired
private AggregationSubService aggregationSubService;
@Autowired
private MatrixAdvRecordMapper advRecordMapper;
@Autowired
private AdminService adminService;
public Integer getAdminId(String deviceId) {
MatrixAdminDevice device = mapper.selectByDeviceId(deviceId);
if (device == null || device.getStatus() == STATUS_OFFLINE) {
@ -37,7 +59,7 @@ public class AdminDeviceService {
return device.getAdminId();
}
public List<MatrixAdminDevice> getDeviceList(Integer adminId, String appCode ) {
public List<MatrixAdminDevice> getDeviceList(Integer adminId, String appCode) {
MatrixApp app = appMapper.queryByCode(appCode);
Assert.isTrue(app != null, "非法请求");
LambdaQueryWrapper<MatrixAdminDevice> queryWrapper = new LambdaQueryWrapper<>();
@ -52,7 +74,7 @@ public class AdminDeviceService {
public String bind(String deviceId, String appCode, String adminName) {
MatrixAdminDevice device = mapper.selectByDeviceId(deviceId);
if(device != null){
if (device != null) {
return "设备已绑定";
}
MatrixAdmin admin = adminMapper.query(adminName);
@ -63,8 +85,8 @@ public class AdminDeviceService {
if (app == null) {
return "应用不存在";
}
if(!StringUtils.hasText(admin.getAppIds()) ||
!Arrays.stream(admin.getAppIds().split(",")).map(Integer::parseInt).toList().contains(app.getId())){
if (!StringUtils.hasText(admin.getAppIds()) ||
!Arrays.stream(admin.getAppIds().split(",")).map(Integer::parseInt).toList().contains(app.getId())) {
return "无权限绑定该应用";
}
long cnt = queryBindCnt(admin.getId(), app.getId());
@ -80,7 +102,7 @@ public class AdminDeviceService {
return "绑定成功";
}
public long queryBindCnt(int adminId, int appId){
public long queryBindCnt(int adminId, int appId) {
LambdaQueryWrapper<MatrixAdminDevice> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MatrixAdminDevice::getAdminId, adminId);
queryWrapper.eq(MatrixAdminDevice::getAppId, appId);
@ -88,5 +110,142 @@ public class AdminDeviceService {
return mapper.selectCount(queryWrapper);
}
public OverviewBo incomeOverview(int adminId, String code) {
if (StringUtils.hasText(code)) {
MatrixApp app = appMapper.queryByCode(code);
if (app == null) {
return new OverviewBo();
}
return incomeOverviewByAppIds(Collections.singletonList(app.getId()), adminId);
}
List<Integer> appIds = adminService.getAdminAppIds(adminId);
if (CollectionUtils.isEmpty(appIds)) {
return new OverviewBo();
}
return incomeOverviewByAppIds(appIds, adminId);
}
private OverviewBo incomeOverviewByAppIds(List<Integer> appIds, int adminId) {
if (CollectionUtils.isEmpty(appIds)) {
return new OverviewBo();
}
LambdaQueryWrapper<MatrixAdvRecord> advQuery = new QueryWrapper<MatrixAdvRecord>()
.select("sum(ecpm) as ecpm").lambda();
advQuery.in(MatrixAdvRecord::getAppId, appIds);
advQuery.gt(MatrixAdvRecord::getCreatedAt, new Timestamp(DateUtil.getDayBeginTimestamp(System.currentTimeMillis())));
advQuery.eq(MatrixAdvRecord::getAdminId, adminId);
MatrixAdvRecord record = advRecordMapper.selectOne(advQuery);
OverviewBo bo = new OverviewBo();
bo.todayIncome = record == null ? 0 : record.getEcpm();
int today = DateUtil.currentDate();
int yesterday = DateUtil.datePlus(today, -1);
bo.yesterdayIncome = aggregationSubService.getIncome(adminId, appIds, yesterday, yesterday);
bo.totalIncome = aggregationSubService.getIncome(adminId, appIds, 20240401, yesterday);
LocalDate now = LocalDate.now();
// 获取上个月的年份和月份
YearMonth lastMonth = YearMonth.from(now).minusMonths(1);
// 获取上个月的第一天和最后一天
LocalDate firstDayOfLastMonth = lastMonth.atDay(1);
LocalDate lastDayOfLastMonth = lastMonth.atEndOfMonth();
bo.lastMonthIncome = aggregationSubService.getIncome(adminId, appIds, DateUtil.date2Number(firstDayOfLastMonth), DateUtil.date2Number(lastDayOfLastMonth));
YearMonth thisMonth = YearMonth.from(now);
// 获取本月的第一天
LocalDate firstDayOfThisMonth = thisMonth.atDay(1);
bo.thisMonthIncome = bo.todayIncome + aggregationSubService.getIncome(adminId, appIds, DateUtil.date2Number(firstDayOfThisMonth), today);
return bo;
}
public List<DateIncome> incomeDaily(IncomeQuery query, int adminId) {
LambdaQueryWrapper<MatrixAdvAggregationSub> wrapper = new QueryWrapper<MatrixAdvAggregationSub>()
.select("date, sum(income_real) as income_real")
.lambda();
if (StringUtils.hasText(query.code)) {
MatrixApp app = appMapper.queryByCode(query.code);
if (app == null) {
return new ArrayList<>();
}
wrapper.eq(MatrixAdvAggregationSub::getAppId, app.getId());
} else {
List<Integer> appIds = adminService.getAdminAppIds(adminId);
if (CollectionUtils.isEmpty(appIds)) {
return new ArrayList<>();
}
wrapper.in(MatrixAdvAggregationSub::getAppId, appIds);
}
if (query.platform != null) {
wrapper.eq(MatrixAdvAggregationSub::getPlatform, query.platform);
}
wrapper.eq(MatrixAdvAggregationSub::getAdminId, adminId);
int end = DateUtil.datePlus(DateUtil.currentDate(), -1), start = DateUtil.datePlus(end, -30);
if (!CollectionUtils.isEmpty(query.date)) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
Date beginDate = format.parse(query.date.get(0)), endDate = format.parse(query.date.get(1));
start = DateUtil.long2Number(beginDate.getTime());
end = DateUtil.long2Number(endDate.getTime());
} catch (ParseException e) {
throw new PaganiException(PaganiExceptionCode.ILLEGAL_REQUEST, "时间范围有误");
}
}
wrapper.between(MatrixAdvAggregationSub::getDate, start, end);
wrapper.groupBy(MatrixAdvAggregationSub::getDate);
wrapper.orderByAsc(MatrixAdvAggregationSub::getDate);
List<MatrixAdvAggregationSub> data = subMapper.selectList(wrapper);
Map<Integer, MatrixAdvAggregationSub> map = data.stream().collect(Collectors.toMap(MatrixAdvAggregationSub::getDate, x -> x));
List<DateIncome> res = new ArrayList<>();
for (int d = start; d <= end; d = DateUtil.datePlus(d, 1)) {
MatrixAdvAggregationSub sub = map.get(d);
DateIncome each = new DateIncome();
each.date = d;
if (sub != null) {
each.income = sub.getIncomeReal();
}
res.add(each);
}
return res;
}
@Scheduled(cron = "0 30 1 * * ?")
public void dailyCalc() {
int yesterday = DateUtil.datePlus(DateUtil.currentDate(), -1);
calcTargetDate(yesterday);
}
public void calcTargetDate(int targetDate) {
long dateBegin = DateUtil.getDayBeginTimestamp(DateUtil.date2Long(targetDate));
long dateEnd = dateBegin + 86400_000 - 1;
LambdaQueryWrapper<MatrixAdvRecord> query = new QueryWrapper<MatrixAdvRecord>()
.select("admin_id, app_id, platform, sum(ecpm) as ecpm")
.lambda();
query.between(MatrixAdvRecord::getCreatedAt, new Timestamp(dateBegin), new Timestamp(dateEnd));
query.eq(MatrixAdvRecord::getAdvType, 3);//设备主只算激励视频
query.gt(MatrixAdvRecord::getAdminId, 0);
query.groupBy(MatrixAdvRecord::getAdminId,MatrixAdvRecord::getAppId, MatrixAdvRecord::getPlatform);
List<MatrixAdvRecord> records = advRecordMapper.selectList(query);
List<MatrixAdvAggregationSub> aggregations = new ArrayList<>();
List<MatrixAdmin> adminList = adminMapper.selectList(null);
Map<Integer, MatrixAdmin> adminMap = adminList.stream().collect(Collectors.toMap(x->x.getId(), x->x));
for (MatrixAdvRecord r : records) {
MatrixAdvAggregationSub aggregation = new MatrixAdvAggregationSub();
aggregation.setAdminId(r.getAdminId());
aggregation.setAppId(r.getAppId());
aggregation.setPlatform(r.getPlatform());
aggregation.setDate(targetDate);
aggregation.setIncome(r.getEcpm());
aggregations.add(aggregation);
aggregation.setIncomeRate(adminMap.get(r.getAdminId()).getIncomeRate());
aggregation.setIncomeReal(aggregation.getIncomeRate() * r.getEcpm() / 100);
}
if (CollectionUtils.isEmpty(aggregations)) {
return;
}
subMapper.insertBatch(aggregations);
}
}

2
game-service/src/main/java/awesome/group/game/service/AdminService.java

@ -366,7 +366,7 @@ public class AdminService {
return bo;
}
private List<Integer> getAdminAppIds(int adminId) {
public List<Integer> getAdminAppIds(int adminId) {
MatrixAdmin admin = adminMapper.selectById(adminId);
if (admin.getRole() == SUPER_ADMIN) {
return appMapper.selectList(null).stream().map(MatrixApp::getId).toList();

34
game-service/src/main/java/awesome/group/game/service/AggregationSubService.java

@ -0,0 +1,34 @@
package awesome.group.game.service;
import awesome.group.game.dao.bean.MatrixAdvAggregationSub;
import awesome.group.game.dao.mapper.MatrixAdvAggregationSubMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
@Service
public class AggregationSubService {
@Resource
private MatrixAdvAggregationSubMapper subMapper;
public long getIncome(int adminId, List<Integer> appIds, int startDate, int endDate) {
if (CollectionUtils.isEmpty(appIds)) {
return 0L;
}
LambdaQueryWrapper<MatrixAdvAggregationSub> query = new QueryWrapper<MatrixAdvAggregationSub>()
.select("sum(income_real) as income").lambda();
query.in(MatrixAdvAggregationSub::getAppId, appIds);
query.between(MatrixAdvAggregationSub::getDate, startDate, endDate);
query.eq(MatrixAdvAggregationSub::getAdminId, adminId);
MatrixAdvAggregationSub data = subMapper.selectOne(query);
if (data == null) {
return 0L;
}
return data.getIncome();
}
}

9
game-service/src/test/java/awesome/group/game/service/AdminServiceTest.java

@ -4,17 +4,18 @@ import awesome.group.game.service.util.DateUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import static org.junit.jupiter.api.Assertions.*;
class AdminServiceTest extends BaseTest{
@Autowired
private AdminService adminService;
@Autowired
private AdminDeviceService deviceService;
@Test
void calcTargetDate() {
int date = 20240401;
int date = 20240315;
for(int i = 1; i < 60; i ++) {
adminService.calcTargetDate(date);
deviceService.calcTargetDate(date);
date = DateUtil.datePlus(date, -1);
}
}

22
game-web/src/main/java/awesome/group/game/web/rest/matrix/DeviceController.java

@ -2,6 +2,9 @@ package awesome.group.game.web.rest.matrix;
import awesome.group.game.dao.bean.MatrixAdminDevice;
import awesome.group.game.service.AdminDeviceService;
import awesome.group.game.service.bo.DateIncome;
import awesome.group.game.service.bo.IncomeQuery;
import awesome.group.game.service.bo.OverviewBo;
import awesome.group.game.service.common.response.R;
import awesome.group.game.web.RequestContext;
import awesome.group.game.web.aop.RestApi;
@ -31,4 +34,23 @@ public class DeviceController {
adminDeviceService.setStatusOffline(RequestContext.getAdminID(), deviceId);
return new R<>("ok");
}
@GetMapping("/incomeOverview")
@RestApi
public R<OverviewBo> incomeOverview(@RequestParam(required = false) String appCode) {
return new R<>(R.CODE_SUCCESS, "ok", adminDeviceService.incomeOverview(RequestContext.getAdminID(), appCode));
}
@PostMapping("/incomeDaily")
@RestApi
public R<List<DateIncome>> incomeDaily(@RequestBody IncomeQuery query) {
return new R<>(R.CODE_SUCCESS, "ok", adminDeviceService.incomeDaily(query, RequestContext.getAdminID()));
}
@GetMapping("/calc")
@RestApi
public R<Void> calc(@RequestParam Integer date) {
adminDeviceService.calcTargetDate(date);
return new R<>();
}
}

Loading…
Cancel
Save