|
@@ -24,8 +24,10 @@ import org.jeecg.common.util.DateUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
|
+import java.lang.reflect.Field;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.text.DecimalFormat;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
@@ -152,133 +154,158 @@ public class KuaiShouRealTimeController {
|
|
|
|
|
|
String nowDate = DateUtils.getNowDate("yyyy-MM-dd");
|
|
|
CtopOauthToken token = tokenService.getTokenByAccountId(accountId);
|
|
|
- //广告主 当天 实时 组 数据信息
|
|
|
- Map unitData = realTimeDataService.getUnitDatePage(accountId, token.getAccessToken(), nowDate, nowDate,pageNum,pageSize);
|
|
|
- //kuaishouReportHourlyGroupService.getAdvertiserGroupReportHourly(accountId,token.getAccessToken(), nowDate,nowDate);
|
|
|
|
|
|
- List<KuaishouReportHourlyGroup> unitList = JSONArray.parseArray(unitData.get("details").toString(),KuaishouReportHourlyGroup.class);
|
|
|
|
|
|
- for (KuaishouReportHourlyGroup unitInfo : unitList) {
|
|
|
- unitInfo.setTotalCount(Integer.valueOf(unitData.get("totalCount").toString()));
|
|
|
+ List<KuaishouReportHourlyGroup> unitList = new ArrayList<>();
|
|
|
+ List<Long> unitIdList = new ArrayList<>();
|
|
|
|
|
|
- //激活成本 = 花费 / 激活数
|
|
|
- String activationCost = "0";
|
|
|
+ //优化目标
|
|
|
+ Integer conver = 0;
|
|
|
+ //获取广告组的出价
|
|
|
+ Map unitPrice = kuaishouInterfaceService.getKuaishouUnitList(token, null,new Date(), new Date() , 1,pageNum,pageSize);
|
|
|
|
|
|
+ JSONArray array = JSONArray.parseArray(unitPrice.get("details").toString());
|
|
|
|
|
|
- if (unitInfo.getCharge().doubleValue() != new Double(0) && unitInfo.getActivation() != 0l){
|
|
|
- Double activation_cost = unitInfo.getCharge().doubleValue() / unitInfo.getActivation();
|
|
|
- activationCost = df.format(activation_cost);
|
|
|
- }
|
|
|
- unitInfo.setActivationCost(activationCost);
|
|
|
+ for (Object obj : array) {
|
|
|
+ KuaishouReportHourlyGroup unitInfo = new KuaishouReportHourlyGroup();
|
|
|
|
|
|
+ unitInfo.setTotalCount(Integer.valueOf(unitPrice.get("totalCount").toString()));
|
|
|
|
|
|
- //获取广告组的出价
|
|
|
- JSONArray unitPrice = kuaishouInterfaceService.getKuaishouUnitList(token, unitInfo.getUnitId(),null, null , 1);
|
|
|
- //优化目标
|
|
|
- Integer conver = 0;
|
|
|
- if(!Check.isNull(unitPrice)){
|
|
|
- JSONObject unitVo = JSONObject.parseObject(unitPrice.get(0).toString());
|
|
|
- //出价
|
|
|
- unitInfo.setBid(Double.valueOf(unitVo.getLong("bid")));
|
|
|
- unitInfo.setBidType(unitVo.getInteger("bid_type"));
|
|
|
- //优化目标
|
|
|
- conver = unitVo.getInteger("ocpx_action_type");
|
|
|
- unitInfo.setConverType(conver);
|
|
|
- }
|
|
|
|
|
|
- //优化目标: 激活, 付费, 行为, 表单提交, 注册, 唤起应用, 关键行为
|
|
|
- //对应转化数 激活数,付费数,行为数,表单提交数,注册数,唤起应用次数,关键行为数
|
|
|
- //优化目标id 来源---ctop_kuaishou_ocpx_action_type_config
|
|
|
- //激活
|
|
|
- if (conver == 180){
|
|
|
- unitInfo.setConverNum(unitInfo.getActivation().intValue());
|
|
|
- }
|
|
|
- //付费
|
|
|
- if (conver == 190){
|
|
|
- unitInfo.setConverNum(unitInfo.getEventPay().intValue());
|
|
|
- }
|
|
|
- //行为
|
|
|
- if (conver == 2){
|
|
|
- unitInfo.setConverNum(unitInfo.getBclick().intValue());
|
|
|
- }
|
|
|
- //表单提交
|
|
|
- if (conver == 53){
|
|
|
- unitInfo.setConverNum(unitInfo.getFormCount().intValue());
|
|
|
- }
|
|
|
- //注册
|
|
|
- if (conver == 396 ){
|
|
|
- unitInfo.setConverNum(unitInfo.getEventRegister().intValue());
|
|
|
- }
|
|
|
- //唤起应用
|
|
|
- if (conver == 324){
|
|
|
- unitInfo.setConverNum(unitInfo.getEventAppInvoked().intValue());
|
|
|
- }
|
|
|
- //关键行为
|
|
|
- if (conver == 773){
|
|
|
- unitInfo.setConverNum(unitInfo.getKeyAction().intValue());
|
|
|
- }
|
|
|
- //转化成本 = 花费 / 转化数
|
|
|
- unitInfo.setConverCost(Check.isNull(unitInfo.getCharge()) || Check.isNull(unitInfo.getConverNum()) ? 0 : unitInfo.getCharge().doubleValue() / unitInfo.getConverNum().doubleValue());
|
|
|
- if (unitInfo.getConverCost().isNaN() || unitInfo.getConverCost().isInfinite()){
|
|
|
- unitInfo.setConverCost(new Double(0));
|
|
|
+ //获取组id
|
|
|
+ JSONObject vo = JSONObject.parseObject(obj.toString());
|
|
|
+ unitIdList.add(vo.getLong("unit_id"));
|
|
|
+
|
|
|
+
|
|
|
+ //广告主 当天 实时 组 数据信息
|
|
|
+ JSONArray unitData = realTimeDataService.getUnitDatePage(accountId, unitIdList, token.getAccessToken(), nowDate, nowDate, pageNum, pageSize);
|
|
|
+ List<KuaishouReportHourlyGroup> k = JSONArray.parseArray(unitData.toString(),KuaishouReportHourlyGroup.class);
|
|
|
+ if (!Check.isNull(k)){
|
|
|
+ unitInfo = k.get(0);
|
|
|
}
|
|
|
|
|
|
- //操作建议
|
|
|
- //消耗
|
|
|
- Double charge = unitInfo.getCharge().doubleValue();
|
|
|
+ unitInfo.setUnitName(vo.getString("unit_name"));
|
|
|
+
|
|
|
//出价
|
|
|
- Double bid = unitInfo.getBid();
|
|
|
- //转化数量
|
|
|
- Integer converNum = unitInfo.getConverNum();
|
|
|
- //转化成本
|
|
|
- Double converCost = unitInfo.getConverCost();
|
|
|
+ unitInfo.setBid(Double.valueOf(vo.getLong("bid")));
|
|
|
+ unitInfo.setBidType(vo.getInteger("bid_type"));
|
|
|
+ //优化目标
|
|
|
+ conver = vo.getInteger("ocpx_action_type");
|
|
|
+ unitInfo.setConverType(conver);
|
|
|
+ //计划id
|
|
|
+ unitInfo.setCampaignId(vo.getLong("campaign_id"));
|
|
|
+ //组id
|
|
|
+ unitInfo.setUnitId(vo.getLong("unit_id"));
|
|
|
+ unitInfo.setUnitName(vo.getString("unit_name"));
|
|
|
|
|
|
+ //激活成本 = 花费 / 激活数
|
|
|
+ String activationCost = "0";
|
|
|
|
|
|
+ if (!Check.isNull(k)){
|
|
|
+ if (unitInfo.getCharge().doubleValue() != new Double(0) && unitInfo.getActivation() != 0l) {
|
|
|
+ Double activation_cost = unitInfo.getCharge().doubleValue() / unitInfo.getActivation();
|
|
|
+ activationCost = df.format(activation_cost);
|
|
|
+ }
|
|
|
|
|
|
- //1. 转化成本大于出价×120%,消耗大于500元:
|
|
|
- if ((converCost > bid * 1.2) && (charge > 500)){
|
|
|
- unitInfo.setOperationAgree("高成本 | 有消耗");
|
|
|
- unitInfo.setOperationAgreeContent("建议限制预算");
|
|
|
- unitInfo.setOperationAgreeInfo("当前广告组转化成本偏高且消耗大于500,建议限制预算;");
|
|
|
- }
|
|
|
- //2. 转化成本大于出价×120%,转化数大于10小于等于50:
|
|
|
- if (converCost > bid * 1.2 && LinkUtils.isInTheInterval(String.valueOf(converNum), "(10,50)")){
|
|
|
- unitInfo.setOperationAgree("高成本 | 有转化");
|
|
|
- unitInfo.setOperationAgreeContent("建议限制预算");
|
|
|
- unitInfo.setOperationAgreeInfo("当前广告组成本大于出价×120%且转化数介于10-50之间;");
|
|
|
- }
|
|
|
- //3. 转化成本大于出价×120%,转化数大于50
|
|
|
- if (converCost > bid * 1.2 && LinkUtils.isInTheInterval(String.valueOf(converNum), "(50,∞)")){
|
|
|
- unitInfo.setOperationAgree("高成本 | 有转化");
|
|
|
- unitInfo.setOperationAgreeContent("建议降低出价;");
|
|
|
- unitInfo.setOperationAgreeInfo("当前转化成本大于出价×120%,转化数大于50,建议降低出价;");
|
|
|
- }
|
|
|
- //4. 转化成本小于等于出价×120%,转化数大于10小于等于50
|
|
|
- if (converCost <= bid * 1.2 && LinkUtils.isInTheInterval(String.valueOf(converNum), "(10,50]")){
|
|
|
- unitInfo.setOperationAgree("成本合理 | 有转化");
|
|
|
- unitInfo.setOperationAgreeContent("建议复制推广组或放开预算");
|
|
|
- unitInfo.setOperationAgreeInfo("当前转化成本小于等于出价×120%,转化数大于10小于等于50,建议复制推广组或放开预算;");
|
|
|
- }
|
|
|
- //5. 消耗大于0小于等于100,转化数大于0小于等于10:
|
|
|
- if (LinkUtils.isInTheInterval(String.valueOf(charge), "(0,100]") && LinkUtils.isInTheInterval(String.valueOf(converNum), "(0,10]")){
|
|
|
- unitInfo.setOperationAgree("消耗少 | 转化少");
|
|
|
- unitInfo.setOperationAgreeContent("建议启用加速探索");
|
|
|
- unitInfo.setOperationAgreeInfo("当前广告组消耗大于0小于等于100,转化数大于0小于等于10,建议加速探索;");
|
|
|
- }
|
|
|
- //6. 消耗大于等于500,转化数等于0:
|
|
|
- if (charge >= 500 && converNum == 0){
|
|
|
- unitInfo.setOperationAgree("有消耗 | 无转化");
|
|
|
- unitInfo.setOperationAgreeContent("建议暂停广告组");
|
|
|
- unitInfo.setOperationAgreeInfo("当前广告组消耗大于等于500且转化数等于0,建议暂停推广组;");
|
|
|
- }
|
|
|
- //7. 消耗大于100小于等于500
|
|
|
- if (LinkUtils.isInTheInterval(String.valueOf(charge), "(100,500]")){
|
|
|
- unitInfo.setOperationAgree("有一定消耗");
|
|
|
- unitInfo.setOperationAgreeContent("建议继续观察");
|
|
|
- unitInfo.setOperationAgreeInfo("当前广告组消耗大于100小于等于500,建议继续观察;");
|
|
|
+ unitInfo.setActivationCost(activationCost);
|
|
|
+
|
|
|
+
|
|
|
+ //优化目标: 激活, 付费, 行为, 表单提交, 注册, 唤起应用, 关键行为
|
|
|
+ //对应转化数 激活数,付费数,行为数,表单提交数,注册数,唤起应用次数,关键行为数
|
|
|
+ //优化目标id 来源---ctop_kuaishou_ocpx_action_type_config
|
|
|
+ //激活
|
|
|
+ if (conver == 180) {
|
|
|
+ unitInfo.setConverNum(unitInfo.getActivation().intValue());
|
|
|
+ }
|
|
|
+ //付费
|
|
|
+ if (conver == 190) {
|
|
|
+ unitInfo.setConverNum(unitInfo.getEventPay().intValue());
|
|
|
+ }
|
|
|
+ //行为
|
|
|
+ if (conver == 2) {
|
|
|
+ unitInfo.setConverNum(unitInfo.getBclick().intValue());
|
|
|
+ }
|
|
|
+ //表单提交
|
|
|
+ if (conver == 53) {
|
|
|
+ unitInfo.setConverNum(unitInfo.getFormCount().intValue());
|
|
|
+ }
|
|
|
+ //注册
|
|
|
+ if (conver == 396) {
|
|
|
+ unitInfo.setConverNum(unitInfo.getEventRegister().intValue());
|
|
|
+ }
|
|
|
+ //唤起应用
|
|
|
+ if (conver == 324) {
|
|
|
+ unitInfo.setConverNum(unitInfo.getEventAppInvoked().intValue());
|
|
|
+ }
|
|
|
+ //关键行为
|
|
|
+ if (conver == 773) {
|
|
|
+ unitInfo.setConverNum(unitInfo.getKeyAction().intValue());
|
|
|
+ }
|
|
|
+ //转化成本 = 花费 / 转化数
|
|
|
+ unitInfo.setConverCost(Check.isNull(unitInfo.getCharge()) || Check.isNull(unitInfo.getConverNum()) ? 0 : unitInfo.getCharge().doubleValue() / unitInfo.getConverNum().doubleValue());
|
|
|
+ if (unitInfo.getConverCost().isNaN() || unitInfo.getConverCost().isInfinite()) {
|
|
|
+ unitInfo.setConverCost(new Double(0));
|
|
|
+ }
|
|
|
+
|
|
|
+ //操作建议
|
|
|
+ //消耗
|
|
|
+ Double charge = unitInfo.getCharge().doubleValue();
|
|
|
+ //出价
|
|
|
+ Double bid = unitInfo.getBid();
|
|
|
+ //转化数量
|
|
|
+ Integer converNum = unitInfo.getConverNum();
|
|
|
+ //转化成本
|
|
|
+ Double converCost = unitInfo.getConverCost();
|
|
|
+
|
|
|
+ //1. 转化成本大于出价×120%,消耗大于500元:
|
|
|
+ if ((converCost > bid * 1.2) && (charge > 500)) {
|
|
|
+ unitInfo.setOperationAgree("高成本 | 有消耗");
|
|
|
+ unitInfo.setOperationAgreeContent("建议限制预算");
|
|
|
+ unitInfo.setOperationAgreeInfo("当前广告组转化成本偏高且消耗大于500,建议限制预算;");
|
|
|
+ }
|
|
|
+ //2. 转化成本大于出价×120%,转化数大于10小于等于50:
|
|
|
+ if (converCost > bid * 1.2 && LinkUtils.isInTheInterval(String.valueOf(converNum), "(10,50)")) {
|
|
|
+ unitInfo.setOperationAgree("高成本 | 有转化");
|
|
|
+ unitInfo.setOperationAgreeContent("建议限制预算");
|
|
|
+ unitInfo.setOperationAgreeInfo("当前广告组成本大于出价×120%且转化数介于10-50之间;");
|
|
|
+ }
|
|
|
+ //3. 转化成本大于出价×120%,转化数大于50
|
|
|
+ if (converCost > bid * 1.2 && LinkUtils.isInTheInterval(String.valueOf(converNum), "(50,∞)")) {
|
|
|
+ unitInfo.setOperationAgree("高成本 | 有转化");
|
|
|
+ unitInfo.setOperationAgreeContent("建议降低出价;");
|
|
|
+ unitInfo.setOperationAgreeInfo("当前转化成本大于出价×120%,转化数大于50,建议降低出价;");
|
|
|
+ }
|
|
|
+ //4. 转化成本小于等于出价×120%,转化数大于10小于等于50
|
|
|
+ if (converCost <= bid * 1.2 && LinkUtils.isInTheInterval(String.valueOf(converNum), "(10,50]")) {
|
|
|
+ unitInfo.setOperationAgree("成本合理 | 有转化");
|
|
|
+ unitInfo.setOperationAgreeContent("建议复制推广组或放开预算");
|
|
|
+ unitInfo.setOperationAgreeInfo("当前转化成本小于等于出价×120%,转化数大于10小于等于50,建议复制推广组或放开预算;");
|
|
|
+ }
|
|
|
+ //5. 消耗大于0小于等于100,转化数大于0小于等于10:
|
|
|
+ if (LinkUtils.isInTheInterval(String.valueOf(charge), "(0,100]") && LinkUtils.isInTheInterval(String.valueOf(converNum), "(0,10]")) {
|
|
|
+ unitInfo.setOperationAgree("消耗少 | 转化少");
|
|
|
+ unitInfo.setOperationAgreeContent("建议启用加速探索");
|
|
|
+ unitInfo.setOperationAgreeInfo("当前广告组消耗大于0小于等于100,转化数大于0小于等于10,建议加速探索;");
|
|
|
+ }
|
|
|
+ //6. 消耗大于等于500,转化数等于0:
|
|
|
+ if (charge >= 500 && converNum == 0) {
|
|
|
+ unitInfo.setOperationAgree("有消耗 | 无转化");
|
|
|
+ unitInfo.setOperationAgreeContent("建议暂停广告组");
|
|
|
+ unitInfo.setOperationAgreeInfo("当前广告组消耗大于等于500且转化数等于0,建议暂停推广组;");
|
|
|
+ }
|
|
|
+ //7. 消耗大于100小于等于500
|
|
|
+ if (LinkUtils.isInTheInterval(String.valueOf(charge), "(100,500]")) {
|
|
|
+ unitInfo.setOperationAgree("有一定消耗");
|
|
|
+ unitInfo.setOperationAgreeContent("建议继续观察");
|
|
|
+ unitInfo.setOperationAgreeInfo("当前广告组消耗大于100小于等于500,建议继续观察;");
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
+ setFeidValueNotNull(unitInfo);
|
|
|
+
|
|
|
+ unitList.add(unitInfo);
|
|
|
+
|
|
|
+ }
|
|
|
return Result.ok(unitList);
|
|
|
}
|
|
|
|
|
@@ -290,7 +317,31 @@ public class KuaiShouRealTimeController {
|
|
|
|
|
|
|
|
|
|
|
|
+ private void setFeidValueNotNull (Object obj){
|
|
|
+ try {
|
|
|
+ for (Field field: obj.getClass().getDeclaredFields()) {
|
|
|
+ field.setAccessible(true);
|
|
|
+ if (field.get(obj) == null){
|
|
|
+ if (field.getGenericType().toString().equals("class java.lang.String")) {
|
|
|
+ field.set(obj, "0");
|
|
|
+ }else if (field.getGenericType().toString().equals("class java.lang.Integer")) {
|
|
|
+ field.set(obj, 0);
|
|
|
+ }else if (field.getGenericType().toString().equals("class java.lang.Double")) {
|
|
|
+ field.set(obj, 0.0);
|
|
|
+ }else if (field.getGenericType().toString().equals("class java.lang.Long")) {
|
|
|
+ field.set(obj, 0L);
|
|
|
+ }else if(field.getGenericType().toString().equals("class java.math.BigDecimal")){
|
|
|
+ field.set(obj, new BigDecimal(0));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }catch (Exception e){
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|