Bläddra i källkod

头条项目出价预警

zxa 3 år sedan
förälder
incheckning
736964f42c

+ 200 - 9
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/ByteDanceAdvertiserDataServiceImpl.java

@@ -3,19 +3,41 @@ package org.jeecg.modules.bytedance.advertise.service.impl;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import lombok.extern.slf4j.Slf4j;
-import org.jeecg.modules.bytedance.advertise.entity.*;
+import org.jeecg.modules.bytedance.advertise.dockapi.MarketingService;
+import org.jeecg.modules.bytedance.advertise.entity.ByteDanceAdvertisePlan;
+import org.jeecg.modules.bytedance.advertise.entity.ByteDanceCreative;
+import org.jeecg.modules.bytedance.advertise.entity.ByteDanceVideoInfo;
+import org.jeecg.modules.bytedance.advertise.entity.BytedanceImageInfo;
 import org.jeecg.modules.bytedance.advertise.mapper.ByteDanceCreativeMapper;
-import org.jeecg.modules.bytedance.advertise.service.*;
+import org.jeecg.modules.bytedance.advertise.mapper.MonitorBytedanceActionTrackUrlMapper;
+import org.jeecg.modules.bytedance.advertise.service.IByteDanceAdvertisePlanService;
+import org.jeecg.modules.bytedance.advertise.service.IByteDanceAdvertiserDataService;
+import org.jeecg.modules.bytedance.advertise.service.IByteDanceCreativeMaterialService;
+import org.jeecg.modules.bytedance.advertise.service.IByteDanceVideoInfoService;
+import org.jeecg.modules.bytedance.advertise.service.IBytedanceImageInfoService;
 import org.jeecg.modules.bytedance.common.entity.CtopOauthToken;
+import org.jeecg.modules.bytedance.common.entity.UserAllocation;
 import org.jeecg.modules.bytedance.common.service.ICtopOauthTokenService;
-import org.jeecg.modules.bytedance.common.utils.*;
+import org.jeecg.modules.bytedance.common.service.IUserAllocationService;
+import org.jeecg.modules.bytedance.common.utils.Check;
+import org.jeecg.modules.bytedance.common.utils.CorpWexinUtils;
+import org.jeecg.modules.bytedance.common.utils.HttpUtils;
+import org.jeecg.modules.bytedance.common.utils.PropertiesUtils;
+import org.jeecg.modules.bytedance.common.utils.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Primary;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
 import java.math.BigDecimal;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
 
 /**
  * @author 宋英豪
@@ -43,6 +65,15 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
     private ByteDanceCreativeMapper creativeMapper;
     @Autowired
     private IByteDanceVideoInfoService videoInfoService;
+    @Autowired
+    private IUserAllocationService userAllocationService;
+    @Resource
+    private CorpWexinUtils corpWexinUtils;
+    @Resource
+    private MonitorBytedanceActionTrackUrlMapper monitorBytedanceActionTrackUrlMapper;
+    @Resource
+    private MarketingService marketingServiceImpl;
+
 
     @Override
     public JSONObject getAdvertiserList(String token, Long accountId) {
@@ -156,7 +187,7 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
     }
 
     @Override
-    public ByteDanceAdvertisePlan getSinglePlanById(CtopOauthToken token, String id){
+    public ByteDanceAdvertisePlan getSinglePlanById(CtopOauthToken token, String id) {
         JSONArray getIds = new JSONArray();
         getIds.add(id);
         // 请求地址
@@ -232,6 +263,7 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
         }
         for (int i = 0; i < data.size(); i++) {
             JSONObject dataObject = data.getJSONObject(i);
+            checkBidType(token.getAccountId(), dataObject);
             ByteDanceAdvertisePlan advertisePlan = new ByteDanceAdvertisePlan(dataObject, String.valueOf(token.getAccountId()));
             BigDecimal deepCpabid = dataObject.getBigDecimal("deep_cpabid");
             if (null != deepCpabid) {
@@ -242,6 +274,169 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
         getAd(token, pageNum + 1, ids, date, updateDate);
     }
 
+    /**
+     * 校验转化出价,并预警
+     */
+    private void checkBidType(Long accountId, JSONObject detail) {
+        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"));
+            }
+        }
+        if (ocpxMap.isEmpty()) {
+            return;
+        }
+        //深度转化目标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.getString("external_action");
+        //转化目标出价
+        String cpaBid = detail.getString("cpa_bid");
+        //深度转化目标
+        String deepConversionType = detail.getString("deep_external_action");
+        //深度转化目标出价
+        String deepConversionBid = detail.getString("deep_cpabid");
+
+        //计划ID
+        Long planId = detail.getLong("ad_id");
+        //计划名称
+        String planName = detail.getString("name");
+        //投放状态
+        String status = detail.getString("status");
+        //操作状态
+        String optStatus = detail.getString("opt_status");
+        if ("AD_STATUS_ENABLE".equals(optStatus) && "AD_STATUS_DELIVERY_OK".equals(status)) { // 操作状态为‘启用’,广告计划投放状态 为‘投放中’
+            String msgType = "";
+            String msgBid = "";
+
+            //转化目标标识
+            Boolean typeFalg = true;
+            //出价标识
+            Boolean bidFalg = true;
+            //转化目标
+            if (!Check.isNull(ocpxActionType)) {
+                //转化出价
+                String ocpxBid = ocpxMap.get(ocpxActionType);
+                //通过转化目标没有查询到转化出价,判断为转化目标不一致,触发关停
+                if (Check.isNull(ocpxBid)) {
+                    typeFalg = false;
+                    msgType = "转化:" + ocpxActionType;
+                } else {
+                    //未查询到转化出价,说明出价不一致,触发出价关停。
+                    if (Check.isNull(cpaBid)) {
+                        bidFalg = false;
+                        msgBid = "出价为空";
+                    } else {
+                        BigDecimal cpa = new BigDecimal(cpaBid);
+                        BigDecimal ocpx = new BigDecimal(ocpxBid);
+                        if (cpa.compareTo(ocpx) == 1) {
+                            //计划转化出价cpa 大于 项目设置最大转化出价,则关停
+                            bidFalg = false;
+                            msgBid = "计划出价:" + cpaBid;
+                        }
+                    }
+                }
+            }
+            //深度转化目标
+            if (typeFalg && bidFalg) {
+                if (!Check.isNull(deepConversionType) && !deepMap.isEmpty()) {
+                    String deepBid = deepMap.get(deepConversionType);
+                    if (Check.isNull(deepBid)) {
+                        //通过key未获取值,说明不包含该目标,进行关停
+                        typeFalg = false;
+                        msgType = "(深度)转化:" + deepConversionType;
+                    } else {
+                        //未查询到转化出价,说明出价不一致,触发出价关停。
+                        if (Check.isNull(deepConversionBid)) {
+                            bidFalg = false;
+                            msgBid = "(深度)出价为空";
+                        } else {
+                            BigDecimal cpa = new BigDecimal(deepConversionBid);
+                            BigDecimal ocpx = new BigDecimal(deepBid);
+                            if (cpa.compareTo(ocpx) == 1) {
+                                //计划转化出价cpa 大于 项目设置最大转化出价,则关停
+                                bidFalg = false;
+                                msgBid = "(深度)计划出价:" + cpaBid;
+                            }
+                        }
+                    }
+                }
+            }
+            if (!typeFalg) { // 出价方式设置非法
+                String text = getBidTypeText(json.getString("projectName"), accountId, planId, planName, msgType);
+                sendMsg(accountId, planId, text);
+            }
+            if (!bidFalg) {
+                String text = getOverBidMessage(json.getString("projectName"), accountId, planId, planName, msgBid);
+                sendMsg(accountId, planId, text);
+            }
+        }
+
+    }
+
+    private void sendMsg(Long accountId, Long planId, String text) {
+        //关停计划
+        CtopOauthToken token = tokenService.getTokenByAccountId(accountId);
+        marketingServiceImpl.updPlanStatus(token, Arrays.asList(planId), "disable");
+        log.info("出价方式预警,accountId:{}==>计划id:{}=====转化目标不一致,计划已【关停】============", accountId, planId);
+        try {
+            UserAllocation account = userAllocationService.getByAccountId(accountId);
+            String userId = "";
+            if (!Check.isNull(account)) {
+                userId = account.getUserId();
+            }
+            JSONObject jsonObject = monitorBytedanceActionTrackUrlMapper.getWChatIdByUserId(userId);
+            corpWexinUtils.sendMessageByWeChatId(jsonObject, text);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    //转化方式错误消息生成
+    private String getBidTypeText(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(msgType).append("<br/>")
+                .append("系统已执行暂停此计划,请您及时查看!");
+        return text.toString();
+    }
+
+    //出价过高预警消息生成
+    private String getOverBidMessage(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(msgBid).append("<br/>")
+                .append("系统已执行暂停此计划,请您及时查看!");
+        return text.toString();
+    }
+
+
     @Override
     public Map<String, Object> getAdvertiserPlan(CtopOauthToken token, String ids, String date, String updateDate) {
         getAd(token, 1, ids, date, updateDate);
@@ -286,8 +481,6 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
     }
 
 
-
-
     private void getCreativeByPage(CtopOauthToken token, String date, int pageNum) {
         JSONObject resultObject = getCreative(token, date, pageNum);
         Integer code = resultObject.getInteger("code");
@@ -475,8 +668,6 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
     }
 
 
-
-
     /**
      * 获取流量包数据接口
      *

+ 1 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/UserAllocationMapper.java

@@ -47,4 +47,5 @@ public interface UserAllocationMapper extends BaseMapper<UserAllocation> {
     Set<String> recursiveQuerySubordinateByLeader(@Param("leaderId") String leaderId);
     Set<String> recursiveQuerySubordinateByLeaders(@Param("leaderIds") Set<String> leaderId);
 
+    JSONObject getProjectByAccountId(Long accountId);
 }

+ 15 - 1
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/xml/UserAllocationMapper.xml

@@ -173,7 +173,21 @@
         </foreach>
     </select>
 
-
+    <select id="getProjectByAccountId" resultType="java.lang.String">
+        select id                   'projectId',
+               project_name         'projectName',
+               max_bid              'maxBid',
+               bid_type             'bidType',
+               ocpx_action_type     'ocpxActionType',
+               deep_conversion_type 'deepConversionType'
+        from ctop_project
+        where id = (
+            select project_id
+            from ctop_user_allocation
+            where account_id = #{accountId}
+            limit 1
+            )
+    </select>
 
 
 </mapper>

+ 2 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/IUserAllocationService.java

@@ -45,4 +45,6 @@ public interface IUserAllocationService extends IService<UserAllocation> {
 
     //递归查询下级
     Set<String> recursiveQuerySubordinate(String userId);
+
+    JSONObject getProjectByAccountId(Long accountId);
 }

+ 6 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/impl/UserAllocationServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.jeecg.modules.bytedance.common.entity.UserAllocation;
 import org.jeecg.modules.bytedance.common.mapper.UserAllocationMapper;
 import org.jeecg.modules.bytedance.common.service.IUserAllocationService;
+import org.jeecg.modules.bytedance.common.utils.Check;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
@@ -154,6 +155,11 @@ public class UserAllocationServiceImpl extends ServiceImpl<UserAllocationMapper,
         return result;
     }
 
+    @Override
+    public JSONObject getProjectByAccountId(Long accountId) {
+        return baseMapper.getProjectByAccountId(accountId);
+    }
+
     //递归查询
     private Set<String> querySubordinate(Set<String> leaderIds, Set<String> result) {
         if (leaderIds.isEmpty()) {