|
@@ -267,11 +267,17 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
|
|
if (!Check.isNull(userAllocation)) {
|
|
if (!Check.isNull(userAllocation)) {
|
|
projectId = userAllocation.getProjectId();
|
|
projectId = userAllocation.getProjectId();
|
|
}
|
|
}
|
|
|
|
+ //忽略账户集合
|
|
|
|
+ List<Long> filterList = new ArrayList<>();
|
|
|
|
+ filterList.add(1754076318295055L);
|
|
|
|
+ filterList.add(1754076317380623L);
|
|
|
|
+ filterList.add(1756429037472775L);
|
|
|
|
+ filterList.add(1748459932225613L);
|
|
|
|
+ filterList.add(1759961630825486L);
|
|
|
|
+ filterList.add(1759961631587399L);
|
|
for (int i = 0; i < data.size(); i++) {
|
|
for (int i = 0; i < data.size(); i++) {
|
|
JSONObject dataObject = data.getJSONObject(i);
|
|
JSONObject dataObject = data.getJSONObject(i);
|
|
- if (projectId != 10080885L && accountId != 1754076318295055L && accountId != 1754076317380623L && accountId != 1756429037472775L
|
|
|
|
- && accountId != 1748459932225613L && accountId != 1759961630825486L && accountId != 1759961631587399L
|
|
|
|
- ) {
|
|
|
|
|
|
+ if (projectId != 10080885L && !filterList.contains(accountId)) {
|
|
checkBidType(accountId, dataObject);
|
|
checkBidType(accountId, dataObject);
|
|
}
|
|
}
|
|
ByteDanceAdvertisePlan advertisePlan = new ByteDanceAdvertisePlan(dataObject, String.valueOf(accountId));
|
|
ByteDanceAdvertisePlan advertisePlan = new ByteDanceAdvertisePlan(dataObject, String.valueOf(accountId));
|
|
@@ -282,6 +288,10 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
|
|
advertisePlanService.saveOrUpdate(advertisePlan);
|
|
advertisePlanService.saveOrUpdate(advertisePlan);
|
|
}
|
|
}
|
|
getAd(token, pageNum + 1, ids, date, updateDate);
|
|
getAd(token, pageNum + 1, ids, date, updateDate);
|
|
|
|
+ // 校验 V3.0 项目列表
|
|
|
|
+ if (projectId != 10080885L && !filterList.contains(accountId)) {
|
|
|
|
+ checkProject(token, date, 1);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -408,22 +418,26 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
|
|
}
|
|
}
|
|
if (!typeFalg) { // 出价方式设置非法
|
|
if (!typeFalg) { // 出价方式设置非法
|
|
String text = getBidTypeText(json.getString("projectName"), accountId, planId, planName, msgType);
|
|
String text = getBidTypeText(json.getString("projectName"), accountId, planId, planName, msgType);
|
|
- sendMsg(accountId, planId, text);
|
|
|
|
|
|
+ sendMsg(accountId, planId, text, "plan");
|
|
detail.put("opt_status", "opt_AD_STATUS_DISABLE");
|
|
detail.put("opt_status", "opt_AD_STATUS_DISABLE");
|
|
}
|
|
}
|
|
if (!bidFalg) {
|
|
if (!bidFalg) {
|
|
String text = getOverBidMessage(json.getString("projectName"), accountId, planId, planName, msgBid);
|
|
String text = getOverBidMessage(json.getString("projectName"), accountId, planId, planName, msgBid);
|
|
- sendMsg(accountId, planId, text);
|
|
|
|
|
|
+ sendMsg(accountId, planId, text, "plan");
|
|
detail.put("opt_status", "opt_AD_STATUS_DISABLE");
|
|
detail.put("opt_status", "opt_AD_STATUS_DISABLE");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- private void sendMsg(Long accountId, Long planId, String text) {
|
|
|
|
|
|
+ private void sendMsg(Long accountId, Long planId, String text, String type) {
|
|
//关停计划
|
|
//关停计划
|
|
CtopOauthToken token = tokenService.getTokenByAccountId(accountId);
|
|
CtopOauthToken token = tokenService.getTokenByAccountId(accountId);
|
|
- marketingServiceImpl.updPlanStatus(token, Arrays.asList(planId), "disable");
|
|
|
|
|
|
+ if ("plan".equals(type)) {
|
|
|
|
+ marketingServiceImpl.updPlanStatus(token, Arrays.asList(planId), "disable");
|
|
|
|
+ } else {
|
|
|
|
+ marketingServiceImpl.updProjectStatus(token, planId, "DISABLE");
|
|
|
|
+ }
|
|
log.info(">预警<,账户:{}=>计划:{}现已【关停】---> {}", accountId, planId, text);
|
|
log.info(">预警<,账户:{}=>计划:{}现已【关停】---> {}", accountId, planId, text);
|
|
try {
|
|
try {
|
|
UserAllocation account = userAllocationService.getByAccountId(accountId);
|
|
UserAllocation account = userAllocationService.getByAccountId(accountId);
|
|
@@ -884,5 +898,209 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
|
|
getBytedancePlanList(accountId, accessToken, pageNum + 1, createDate, updateDate);
|
|
getBytedancePlanList(accountId, accessToken, pageNum + 1, createDate, updateDate);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public void checkProject(CtopOauthToken oauthToken, String date, int page) {
|
|
|
|
+ log.info("获取项目列表 accountId:{},日期:{},page:{}", oauthToken.getAccountId(), date, page);
|
|
|
|
+ try {
|
|
|
|
+ // 请求地址
|
|
|
|
+ String url = bytedanceApiUrl + "/v3.0/project/list/";
|
|
|
|
+ JSONObject param = new JSONObject();
|
|
|
|
+ param.put("advertiser_id", oauthToken.getAccountId());
|
|
|
|
+ param.put("page", page);
|
|
|
|
+ param.put("page_size", 100);
|
|
|
|
+ JSONObject filtering = new JSONObject();
|
|
|
|
+ filtering.put("project_modify_time", date);
|
|
|
|
+ filtering.put("project_create_time", date);
|
|
|
|
+ param.put("filtering", filtering);
|
|
|
|
+ JSONObject resultObject = HttpUtils.bytedanceGetRequest(oauthToken.getAccessToken(), url, param);
|
|
|
|
+ if (Check.isNull(resultObject)) {
|
|
|
|
+ log.error("获取项目列表异常==》accountId:{},调用结果为null", oauthToken.getAccountId());
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ Integer code = resultObject.getInteger("code");
|
|
|
|
+ if (null == code || !code.equals(0)) {
|
|
|
|
+ log.error("获取获取项目列表接口异常==》accountId:{},message:{},code{}", oauthToken.getAccountId(), resultObject.getString("message"), code);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ JSONArray data = resultObject.getJSONObject("data").getJSONArray("list");
|
|
|
|
+ if (null == data || data.isEmpty()) {
|
|
|
|
+ log.error("获取获取项目列表数据为空==》accountId:{},message:{},code:{}", oauthToken.getAccountId(), resultObject.getString("message"), code);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ for (int i = 0; i < data.size(); i++) {
|
|
|
|
+ JSONObject object = data.getJSONObject(i);
|
|
|
|
+ checkProjectBidType(object);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ page++;
|
|
|
|
+ int totalPage = resultObject.getJSONObject("data").getJSONObject("page_info").getInteger("total_page");
|
|
|
|
+ if (page <= totalPage) {
|
|
|
|
+ checkProject(oauthToken, date, page);
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 校验转化出价,并预警
|
|
|
|
+ */
|
|
|
|
+ public void checkProjectBidType(JSONObject detail) {
|
|
|
|
+ Long accountId = detail.getLong("advertiser_id");
|
|
|
|
+ JSONObject json = userAllocationService.getProjectByAccountId(accountId);
|
|
|
|
+ if (Check.isNull(json) || Check.isNull(detail)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ //转化目标map
|
|
|
|
+ Map<String, String> ocpxMap = new HashMap<>();
|
|
|
|
+ String ocpxTypeStr = json.getString("ocpxActionType");
|
|
|
|
+ if (!Check.isNull(ocpxTypeStr)) {
|
|
|
|
+ JSONArray ocpxArr = JSONArray.parseArray(ocpxTypeStr);
|
|
|
|
+ for (int i = 0; i < ocpxArr.size(); i++) {
|
|
|
|
+ JSONObject obj = ocpxArr.getJSONObject(i);
|
|
|
|
+ ocpxMap.put(obj.getString("ocpxCode"), obj.getString("maxValue"));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //深度转化目标map
|
|
|
|
+ Map<String, String> deepMap = new HashMap<>();
|
|
|
|
+ String deepTypeStr = json.getString("deepConversionType");
|
|
|
|
+ if (!Check.isNull(deepTypeStr)) {
|
|
|
|
+ JSONArray deepArr = JSONArray.parseArray(deepTypeStr);
|
|
|
|
+ for (int i = 0; i < deepArr.size(); i++) {
|
|
|
|
+ JSONObject obj = deepArr.getJSONObject(i);
|
|
|
|
+ deepMap.put(obj.getString("deepCode"), obj.getString("deepValue"));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //转化目标
|
|
|
|
+ String ocpxActionType = detail.getJSONObject("optimize_goal").getString("external_action");
|
|
|
|
+ //转化目标出价
|
|
|
|
+ String cpaBid = detail.getJSONObject("delivery_setting").getString("cpa_bid");
|
|
|
|
+ //深度转化目标
|
|
|
|
+ String deepConversionType = detail.getJSONObject("optimize_goal").getString("deep_external_action");
|
|
|
|
+ //深度转化目标出价
|
|
|
|
+ String deepConversionBid = detail.getJSONObject("delivery_setting").getString("deep_cpabid");
|
|
|
|
+
|
|
|
|
+ //计划ID
|
|
|
|
+ Long planId = detail.getLong("project_id");
|
|
|
|
+ //计划名称
|
|
|
|
+ String planName = detail.getString("name");
|
|
|
|
+ //操作状态
|
|
|
|
+ String optStatus = detail.getString("opt_status");// ENABLE 启用项目、 DISABLE 暂停项目
|
|
|
|
+// if (true) { // 操作状态为‘启用’,广告计划投放状态 非‘暂停’
|
|
|
|
+ if ("ENABLE".equals(optStatus)) {
|
|
|
|
+ Map<String, String> textMap = new HashMap<>();
|
|
|
|
+ List<JSONObject> lists = creativeMapper.getBytedanceOcpxTypeList();
|
|
|
|
+ for (JSONObject da : lists) {
|
|
|
|
+ textMap.put(da.getString("ocpxActionType"), da.getString("ocpxActionName"));
|
|
|
|
+ }
|
|
|
|
+ String msgType = "";
|
|
|
|
+ String msgBid = "";
|
|
|
|
+
|
|
|
|
+ //转化目标标识
|
|
|
|
+ Boolean typeFalg = true;
|
|
|
|
+ //出价标识
|
|
|
|
+ Boolean bidFalg = true;
|
|
|
|
+ //转化目标
|
|
|
|
+ if (!Check.isNull(ocpxActionType)) {
|
|
|
|
+ if (ocpxMap.isEmpty()) {
|
|
|
|
+ typeFalg = false;
|
|
|
|
+ String msg = Check.isNull(textMap.get(ocpxActionType)) ? ocpxActionType : textMap.get(ocpxActionType);
|
|
|
|
+ msgType = "未设转化,目标转化:" + msg;
|
|
|
|
+ } else {
|
|
|
|
+ //转化出价
|
|
|
|
+ String ocpxBid = ocpxMap.get(ocpxActionType);
|
|
|
|
+ //通过转化目标没有查询到转化出价,判断为转化目标不一致,触发关停
|
|
|
|
+ if (Check.isNull(ocpxBid)) {
|
|
|
|
+ typeFalg = false;
|
|
|
|
+ String msg = Check.isNull(textMap.get(ocpxActionType)) ? ocpxActionType : textMap.get(ocpxActionType);
|
|
|
|
+ msgType = "目标转化:" + msg;
|
|
|
|
+ } else {
|
|
|
|
+ //未查询到转化出价,说明出价不一致,触发出价关停。
|
|
|
|
+ if (Check.isNull(cpaBid)) {
|
|
|
|
+ bidFalg = false;
|
|
|
|
+ msgBid = "目标出价为空";
|
|
|
|
+ } else {
|
|
|
|
+ BigDecimal cpa = new BigDecimal(cpaBid).multiply(new BigDecimal("1000"));
|
|
|
|
+ BigDecimal ocpx = new BigDecimal(ocpxBid);
|
|
|
|
+ if (cpa.compareTo(ocpx) == 1) {
|
|
|
|
+ //计划转化出价cpa 大于 项目设置最大转化出价,则关停
|
|
|
|
+ bidFalg = false;
|
|
|
|
+ msgBid = "目标出价:" + cpaBid;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //深度转化目标
|
|
|
|
+ if (typeFalg && bidFalg) {
|
|
|
|
+ if (!Check.isNull(deepConversionType) && deepMap.isEmpty()) {
|
|
|
|
+ typeFalg = false;
|
|
|
|
+ String msg = Check.isNull(textMap.get(deepConversionType)) ? deepConversionType : textMap.get(deepConversionType);
|
|
|
|
+ msgType = "未设深度转化,目标深度转化:" + msg;
|
|
|
|
+ } else if (!Check.isNull(deepConversionType)) {
|
|
|
|
+ String deepBid = deepMap.get(deepConversionType);
|
|
|
|
+ if (Check.isNull(deepBid)) {
|
|
|
|
+ //通过key未获取值,说明不包含该目标,进行关停
|
|
|
|
+ typeFalg = false;
|
|
|
|
+ String msg = Check.isNull(textMap.get(deepConversionType)) ? deepConversionType : textMap.get(deepConversionType);
|
|
|
|
+ msgType = "目标深度转化:" + msg;
|
|
|
|
+ } else {
|
|
|
|
+ //未查询到转化出价,说明出价不一致,触发出价关停。
|
|
|
|
+ if (Check.isNull(deepConversionBid)) {
|
|
|
|
+ bidFalg = false;
|
|
|
|
+ msgBid = "目标深度出价为空";
|
|
|
|
+ } else {
|
|
|
|
+ BigDecimal cpa = new BigDecimal(deepConversionBid).multiply(new BigDecimal("1000"));
|
|
|
|
+ BigDecimal ocpx = new BigDecimal(deepBid);
|
|
|
|
+ if (cpa.compareTo(ocpx) == 1) {
|
|
|
|
+ //计划转化出价cpa 大于 项目设置最大转化出价,则关停
|
|
|
|
+ bidFalg = false;
|
|
|
|
+ msgBid = "目标深度出价:" + deepConversionBid;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (!typeFalg) { // 出价方式设置非法
|
|
|
|
+ String text = getProjectBidTypeText(json.getString("projectName"), accountId, planId, planName, msgType);
|
|
|
|
+ sendMsg(accountId, planId, text, "project");
|
|
|
|
+ }
|
|
|
|
+ if (!bidFalg) {
|
|
|
|
+ String text = getProjectOverBidMessage(json.getString("projectName"), accountId, planId, planName, msgBid);
|
|
|
|
+ sendMsg(accountId, planId, text, "project");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //转化方式错误消息生成
|
|
|
|
+ private String getProjectBidTypeText(String projectName, Long advertiserId, Long unitId, String unit_name, String msgType) {
|
|
|
|
+ StringBuilder text = new StringBuilder();
|
|
|
|
+ text.append("出价方式错误预警").append("<br/>")
|
|
|
|
+ .append("您的项目:").append(projectName + ",").append("<br/>")
|
|
|
|
+ .append("下的账户:").append(advertiserId + ",").append("<br/>")
|
|
|
|
+ .append("项目id:").append(unitId).append("<br/>")
|
|
|
|
+ .append("项目名称:").append(unit_name).append("<br/>")
|
|
|
|
+ .append("出价方式设置错误。").append("<br/>")
|
|
|
|
+ .append(msgType).append("<br/>")
|
|
|
|
+ .append("系统已执行暂停此项目,请您及时查看!");
|
|
|
|
+ return text.toString();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //出价过高预警消息生成
|
|
|
|
+ private String getProjectOverBidMessage(String projectName, Long accountId, Long planId, String planName, String msgBid) {
|
|
|
|
+ StringBuilder text = new StringBuilder();
|
|
|
|
+ text.append("出价过高预警").append("<br/>")
|
|
|
|
+ .append("您的项目:").append(projectName + ",").append("<br/>")
|
|
|
|
+ .append("下的账户:").append(accountId + ",").append("<br/>")
|
|
|
|
+ .append("项目id:").append(planId).append("<br/>")
|
|
|
|
+ .append("项目名称:").append(planName).append("<br/>")
|
|
|
|
+ .append("出价设置过高。").append("<br/>")
|
|
|
|
+ .append(msgBid).append("<br/>")
|
|
|
|
+ .append("系统已执行暂停此项目,请您及时查看!");
|
|
|
|
+ return text.toString();
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|