|
@@ -1,30 +1,20 @@
|
|
package cn.com.ctop.toutiao.modules.report.service.impl;
|
|
package cn.com.ctop.toutiao.modules.report.service.impl;
|
|
|
|
|
|
import cn.com.ctop.common.module.entity.CtopOauthToken;
|
|
import cn.com.ctop.common.module.entity.CtopOauthToken;
|
|
-import cn.com.ctop.common.module.mapper.UserAllocationMapper;
|
|
|
|
-import cn.com.ctop.common.module.service.ICtopOauthTokenService;
|
|
|
|
import cn.com.ctop.common.module.utils.Check;
|
|
import cn.com.ctop.common.module.utils.Check;
|
|
import cn.com.ctop.common.module.utils.HttpUtils;
|
|
import cn.com.ctop.common.module.utils.HttpUtils;
|
|
-import cn.com.ctop.common.module.utils.LoadFileUtil;
|
|
|
|
-import cn.com.ctop.toutiao.modules.report.entity.BytedanceDailyReportTask;
|
|
|
|
import cn.com.ctop.toutiao.modules.report.entity.BytedanceReportMaterialDaily;
|
|
import cn.com.ctop.toutiao.modules.report.entity.BytedanceReportMaterialDaily;
|
|
import cn.com.ctop.toutiao.modules.report.entity.BytedanceReportMaterialRetry;
|
|
import cn.com.ctop.toutiao.modules.report.entity.BytedanceReportMaterialRetry;
|
|
import cn.com.ctop.toutiao.modules.report.entity.BytedanceReportVideoMaterialDaily;
|
|
import cn.com.ctop.toutiao.modules.report.entity.BytedanceReportVideoMaterialDaily;
|
|
-import cn.com.ctop.toutiao.modules.report.mapper.BytedanceAdvertiserDailyReportMapper;
|
|
|
|
-import cn.com.ctop.toutiao.modules.report.mapper.BytedanceDailyReportTaskMapper;
|
|
|
|
import cn.com.ctop.toutiao.modules.report.mapper.BytedanceReportMapper;
|
|
import cn.com.ctop.toutiao.modules.report.mapper.BytedanceReportMapper;
|
|
import cn.com.ctop.toutiao.modules.report.mapper.BytedanceReportMaterialDailyMapper;
|
|
import cn.com.ctop.toutiao.modules.report.mapper.BytedanceReportMaterialDailyMapper;
|
|
-import cn.com.ctop.toutiao.modules.report.service.IBytedanceDailyReportTaskService;
|
|
|
|
import cn.com.ctop.toutiao.modules.report.service.IBytedanceReportService;
|
|
import cn.com.ctop.toutiao.modules.report.service.IBytedanceReportService;
|
|
-import com.alibaba.fastjson.JSON;
|
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
import com.alibaba.fastjson.JSONArray;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.jeecg.common.util.DateUtils;
|
|
import org.jeecg.common.util.DateUtils;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
-import org.springframework.context.annotation.Primary;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
@@ -36,31 +26,11 @@ import java.util.Map;
|
|
|
|
|
|
@Service
|
|
@Service
|
|
@Slf4j
|
|
@Slf4j
|
|
-@Primary
|
|
|
|
-
|
|
|
|
public class BytedanceReportServiceImpl implements IBytedanceReportService {
|
|
public class BytedanceReportServiceImpl implements IBytedanceReportService {
|
|
-
|
|
|
|
@Value("${jeecg.path.report-history}")
|
|
@Value("${jeecg.path.report-history}")
|
|
private String downloadPath;
|
|
private String downloadPath;
|
|
@Autowired
|
|
@Autowired
|
|
- private UserAllocationMapper userAllocationMapper;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private BytedanceAdvertiserDailyReportMapper bytedanceAdvertiserDailyReportMapper;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
private BytedanceReportMapper reportMapper;
|
|
private BytedanceReportMapper reportMapper;
|
|
-
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private BytedanceDailyReportTaskMapper bytedanceDailyReportTaskMapper;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private IBytedanceDailyReportTaskService bytedanceDailyReportTaskService;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private ICtopOauthTokenService ctopOauthTokenService;
|
|
|
|
-
|
|
|
|
@Autowired
|
|
@Autowired
|
|
private BytedanceReportMaterialDailyMapper bytedanceReportMaterialDailyMapper;
|
|
private BytedanceReportMaterialDailyMapper bytedanceReportMaterialDailyMapper;
|
|
|
|
|
|
@@ -498,216 +468,6 @@ public class BytedanceReportServiceImpl implements IBytedanceReportService {
|
|
return reportList;
|
|
return reportList;
|
|
}
|
|
}
|
|
|
|
|
|
- /////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- //创建异步任务
|
|
|
|
- @Override
|
|
|
|
- public void bytedanceAsyncTaskCreate(String startDate, String endDate, CtopOauthToken token, Integer type) {
|
|
|
|
- int diffMonths = DateUtils.calDiffMonth(DateUtils.parseDate(startDate, "yyyy-MM-dd"), DateUtils.parseDate(endDate, "yyyy-MM-dd"));
|
|
|
|
- if (diffMonths == 0) {
|
|
|
|
- bytedanceAsyncTaskCreateByMonth(startDate, endDate, token, type);
|
|
|
|
- } else {
|
|
|
|
- for (int i = 0; i <= diffMonths; i++) {
|
|
|
|
- if (i == 0) {
|
|
|
|
- Map<String, String> dateMap = DateUtils.getMaxMinDaysOfAddMonth(startDate, "yyyy-MM-dd", i);
|
|
|
|
- String end = dateMap.get("endDate");
|
|
|
|
- bytedanceAsyncTaskCreateByMonth(startDate, end, token, type);
|
|
|
|
- } else if (i == diffMonths) {
|
|
|
|
- Map<String, String> dateMap = DateUtils.getMaxMinDaysOfAddMonth(startDate, "yyyy-MM-dd", i);
|
|
|
|
- String start = dateMap.get("startDate");
|
|
|
|
- bytedanceAsyncTaskCreateByMonth(start, endDate, token, type);
|
|
|
|
- } else {
|
|
|
|
- Map<String, String> dateMap = DateUtils.getMaxMinDaysOfAddMonth(startDate, "yyyy-MM-dd", i);
|
|
|
|
- String start = dateMap.get("startDate");
|
|
|
|
- String end = dateMap.get("endDate");
|
|
|
|
- bytedanceAsyncTaskCreateByMonth(start, end, token, type);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /***
|
|
|
|
- * 由于异步拉取数据不能跨月,故只能按月循环拉取
|
|
|
|
- * @param startDate
|
|
|
|
- * @param endDate
|
|
|
|
- * @param token
|
|
|
|
- */
|
|
|
|
- private void bytedanceAsyncTaskCreateByMonth(String startDate, String endDate, CtopOauthToken token, Integer type) {
|
|
|
|
- String access_token = token.getAccessToken();
|
|
|
|
- Long accountId = token.getAccountId();
|
|
|
|
-
|
|
|
|
- // 请求地址
|
|
|
|
- String open_api_domain = "https://ad.toutiao.com";
|
|
|
|
- String path = "/open_api/2/async_task/create/";
|
|
|
|
-
|
|
|
|
- String taskName = System.currentTimeMillis() + "";
|
|
|
|
- // 请求参数
|
|
|
|
- final Map filtering = new HashMap() {
|
|
|
|
- {
|
|
|
|
- put("start_date", startDate);
|
|
|
|
- put("end_date", endDate);
|
|
|
|
- if (type == 1) {//创意
|
|
|
|
- put("group_by", new String[]{"STAT_GROUP_BY_CREATIVE_ID", "STAT_GROUP_BY_TIME_DAY", "STAT_GROUP_BY_CREATIVE_MATERIAL_MODE"}); //按照创意分组、天分组、创意类型分组查询
|
|
|
|
- } else if (type == 2) {//广告主
|
|
|
|
- put("group_by", new String[]{"STAT_GROUP_BY_ADVERTISER_ID", "STAT_GROUP_BY_TIME_DAY", "STAT_GROUP_BY_PRICING_CATEGORY"}); //按照广告主分组、天分组、广告类型类型分组查询
|
|
|
|
- } else if (type == 3) {//广告组
|
|
|
|
- put("group_by", new String[]{"STAT_GROUP_BY_CAMPAIGN_ID", "STAT_GROUP_BY_TIME_DAY", "STAT_GROUP_BY_CAMPAIGN_TYPE"}); //按照广告组、天、广告组类型分组
|
|
|
|
- } else {//4广告计划
|
|
|
|
- put("group_by", new String[]{"STAT_GROUP_BY_AD_ID", "STAT_GROUP_BY_TIME_DAY", "STAT_GROUP_BY_LANDING_TYPE"}); //按照广告计划、天、推广类型分组
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- final Map data = new HashMap() {
|
|
|
|
- {
|
|
|
|
- put("advertiser_id", accountId);
|
|
|
|
- put("task_name", taskName);
|
|
|
|
- put("task_type", "REPORT");
|
|
|
|
- put("task_params", filtering);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- JSONObject json = HttpUtils.bytedancePostRequest(access_token, open_api_domain + path, JSONObject.parseObject(JSONObject.toJSONString(data)));
|
|
|
|
- if (json == null) {
|
|
|
|
- log.error("请求有误:" + JSONObject.toJSONString(data));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- String jsonString = JSON.toJSONString(json);
|
|
|
|
-
|
|
|
|
- if (!Check.isNull(json)) {
|
|
|
|
- Integer code = json.getInteger("code");
|
|
|
|
- if (code != 0) {
|
|
|
|
- log.error("返回信息错误,错误码为:" + code + ",头条accountId:" + accountId + ",message:" + json.getString("message"));
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- JSONObject dataJson = json.getJSONObject("data");
|
|
|
|
-
|
|
|
|
- //解析数据并入库
|
|
|
|
- BytedanceDailyReportTask task = new BytedanceDailyReportTask();
|
|
|
|
- task.setAccountId(accountId);
|
|
|
|
- task.setTaskCreateTime(dataJson.getDate("create_time") == null ? null : dataJson.getDate("create_time"));
|
|
|
|
- task.setTaskId(dataJson.getLong("task_id") == null ? null : dataJson.getLong("task_id"));
|
|
|
|
- task.setTaskName(dataJson.getString("task_name") == null ? null : dataJson.getString("task_name"));
|
|
|
|
- task.setTaskParams(JSON.toJSONString(dataJson.getJSONObject("task_params")));
|
|
|
|
- task.setJson(jsonString);
|
|
|
|
- task.setTaskStatus(dataJson.getString("task_status"));
|
|
|
|
- task.setTaskType(dataJson.getString("task_type"));
|
|
|
|
- task.setType(type);
|
|
|
|
- task.setIsDownload(0);
|
|
|
|
- task.setStatus(1); //状态1正常 0废弃
|
|
|
|
- bytedanceDailyReportTaskMapper.insert(task);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //获取任务列表
|
|
|
|
- @Override
|
|
|
|
- public void bytedanceAsyncTaskGet() {
|
|
|
|
- QueryWrapper<BytedanceDailyReportTask> taskQueryWrapper = new QueryWrapper<>();
|
|
|
|
- //查询三种状态的信息--任务已创建、任务执行中、任务处理中
|
|
|
|
- taskQueryWrapper.eq("is_download", 0);
|
|
|
|
- //taskQueryWrapper.in("task_status", "ASYNC_TASK_STATUS_CREATED","ASYNC_TASK_STATUS_EXECUTING","ASYNC_TASK_STATUS_EXECUTING_STAGE2");
|
|
|
|
- taskQueryWrapper.notIn("task_status", "ASYNC_TASK_STATUS_FAILED");
|
|
|
|
- taskQueryWrapper.orderByDesc("create_time");
|
|
|
|
- List<BytedanceDailyReportTask> taskList = bytedanceDailyReportTaskService.list(taskQueryWrapper);
|
|
|
|
-
|
|
|
|
- if (!Check.isNull(taskList)) {
|
|
|
|
- for (BytedanceDailyReportTask task : taskList) {
|
|
|
|
- CtopOauthToken token = ctopOauthTokenService.getTokenByAccountId(task.getAccountId());
|
|
|
|
-
|
|
|
|
- if (!Check.isNull(token)) {
|
|
|
|
- // 请求地址
|
|
|
|
- String open_api_domain = "https://ad.toutiao.com";
|
|
|
|
- String path = "/open_api/2/async_task/get/";
|
|
|
|
-
|
|
|
|
- String access_token = token.getAccessToken();
|
|
|
|
- Long accountId = task.getAccountId();
|
|
|
|
- final Long advertiser_id = accountId;
|
|
|
|
-
|
|
|
|
- // 请求参数
|
|
|
|
- final Map filtering = new HashMap() {
|
|
|
|
- {
|
|
|
|
- put("task_ids", new Long[]{task.getTaskId()});
|
|
|
|
- put("task_name", task.getTaskName());
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- Map data = new HashMap() {
|
|
|
|
- {
|
|
|
|
- put("advertiser_id", advertiser_id);
|
|
|
|
- put("filtering", filtering);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- JSONObject json = HttpUtils.bytedanceGetRequest(access_token, open_api_domain + path, JSONObject.parseObject(JSONObject.toJSONString(data)));
|
|
|
|
- if (json == null) {
|
|
|
|
- log.error("请求有误:" + JSONObject.toJSONString(data));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- try {
|
|
|
|
- String jsonString = JSON.toJSONString(json);
|
|
|
|
- //log.info("返回json为" + jsonString);
|
|
|
|
-
|
|
|
|
- if (!Check.isNull(json)) {
|
|
|
|
- Integer code = json.getInteger("code");
|
|
|
|
- if (code != 0) {
|
|
|
|
- log.info("获取任务列表返回信息错误,错误码为:" + code + ",头条accountId:" + accountId + "taskId:" + task.getTaskId());
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- JSONObject jsonData = json.getJSONObject("data");
|
|
|
|
- if (Check.isNull(jsonData)) {
|
|
|
|
- log.error("获取任务列表返回信息data内容为空");
|
|
|
|
- }
|
|
|
|
- JSONArray jsonArrayay = jsonData.getJSONArray("list");
|
|
|
|
-
|
|
|
|
- for (int i = 0; i < jsonArrayay.size(); i++) {
|
|
|
|
- JSONObject detailJson = jsonArrayay.getJSONObject(i);
|
|
|
|
- if (!Check.isNull(detailJson)) {
|
|
|
|
- String taskStatus = detailJson.getString("task_status");
|
|
|
|
-
|
|
|
|
- if ("ASYNC_TASK_STATUS_COMPLETED".equals(taskStatus)) {
|
|
|
|
- bytedanceAsyncTaskDownload(task, token, task.getType());
|
|
|
|
- task.setIsDownload(1);
|
|
|
|
- }
|
|
|
|
- task.setTaskStatus(taskStatus);
|
|
|
|
- bytedanceDailyReportTaskMapper.updateById(task);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } catch (Exception e) {
|
|
|
|
- e.printStackTrace();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //下载任务结果 type 1.creative 2.account 3.campaign 4.plan
|
|
|
|
- private void bytedanceAsyncTaskDownload(BytedanceDailyReportTask task, CtopOauthToken token, Integer type) {
|
|
|
|
- // 请求地址
|
|
|
|
- String open_api_domain = "https://ad.toutiao.com";
|
|
|
|
- String path = "/open_api/2/async_task/download/";
|
|
|
|
-
|
|
|
|
- String url = open_api_domain + path;
|
|
|
|
- String fileName = task.getAccountId() + "_" + "type" + type + "_" + task.getTaskId() + "_" + System.currentTimeMillis() + ".csv";
|
|
|
|
- Map<String, Object> requestMap = new HashMap<>();
|
|
|
|
- requestMap.put("advertiser_id", task.getAccountId());
|
|
|
|
- requestMap.put("task_id", task.getTaskId());
|
|
|
|
- String localPath = LoadFileUtil.downloadByUrl(requestMap, downloadPath, url, token.getAccessToken(), fileName);
|
|
|
|
- if (type == 1) {
|
|
|
|
- //素材异步报表
|
|
|
|
- bytedanceDailyReportTaskMapper.loadBytedanceDailyCreativeFileAsync(localPath);
|
|
|
|
- } else if (type == 2) {
|
|
|
|
- //账户异步报表
|
|
|
|
- bytedanceDailyReportTaskMapper.loadBytedanceDailyAccountFileAsync(localPath);
|
|
|
|
- } else if (type == 3) {
|
|
|
|
- //campaign异步报表
|
|
|
|
- bytedanceDailyReportTaskMapper.loadBytedanceDailyCampaignFileAsync(localPath);
|
|
|
|
- } else if (type == 4) {
|
|
|
|
- //plan异步报表
|
|
|
|
- bytedanceDailyReportTaskMapper.loadBytedanceDailyPlanFileAsync(localPath);
|
|
|
|
- } else {
|
|
|
|
- log.error("异步报表类型传入错误,task_id:" + task.getTaskId() + ";类型:" + type);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/////////////////////////////////////////////////////////\
|
|
/////////////////////////////////////////////////////////\
|
|
//素材报表
|
|
//素材报表
|
|
@Override
|
|
@Override
|