瀏覽代碼

Merge remote-tracking branch 'origin/master'

yumeng 1 年之前
父節點
當前提交
dcf9e3d624
共有 24 個文件被更改,包括 880 次插入 和 66 次删除
  1. 15 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/controller/BytedanceController.java
  2. 10 2
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/controller/FeishuController.java
  3. 7 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/entity/AigcProductAlbum.java
  4. 3 1
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/entity/AigcProductPlatform.java
  5. 10 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/BytedanceProductUpdateMapper.java
  6. 2 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/BytedancePromoterReportMapper.java
  7. 51 4
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/xml/BytedanceProductUpdateMapper.xml
  8. 6 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/xml/BytedancePromoterReportMapper.xml
  9. 17 5
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/xml/ReportsAdPushMapper.xml
  10. 7 1
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/IBytedanceProductUpdateService.java
  11. 17 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/IFeishuDocSyncService.java
  12. 2 4
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedanceCdpProjectServiceImpl.java
  13. 8 3
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedanceMaterialReportServiceImpl.java
  14. 4 1
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedanceMiniAppServiceImpl.java
  15. 335 21
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedanceProductUpdateServiceImpl.java
  16. 253 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/FeishuDocSyncServiceImpl.java
  17. 8 13
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/ReportsAdPushServiceImpl.java
  18. 6 5
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/ReportsByBusinessPushServiceImpl.java
  19. 10 1
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/handler/BytedanceProductUploadJob.java
  20. 16 4
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/handler/BytedanceReportRetryJob.java
  21. 4 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/handler/ToolsSiteJob.java
  22. 39 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/utils/BytedanceProductDocProperties.java
  23. 5 0
      job-bytedance/src/main/java/cn/com/ctop/job/bytedance/utils/FeishuRobotUtil.java
  24. 45 1
      job-bytedance/src/main/resources/application.yml

+ 15 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/controller/BytedanceController.java

@@ -330,6 +330,21 @@ public class BytedanceController {
         }
     }
 
+    @GetMapping("/promoterDaily")
+    public void promoterDaily(@RequestParam(required = false) Long advertiserId, String startDate, String endDate) {
+        List<JSONObject> costAccount = productReportService.getCostAccount(advertiserId, startDate, endDate);
+        for (JSONObject jsonObject : costAccount) {
+            executor10Service1.submit(() -> {
+                Long adverId = jsonObject.getLong("advertiserId");
+                String accessToken = jsonObject.getString("accessToken");
+                promoterReportService.getBytedancePromoterDaily(adverId, accessToken, startDate, endDate, 1, 1);
+            });
+        }
+    }
+
+
+
+
 
     @GetMapping("/getWxAppInfo")
     public void getWxAppInfo(Long advertiserId) {

+ 10 - 2
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/controller/FeishuController.java

@@ -48,6 +48,8 @@ public class FeishuController {
     private IDistributionPushService distributionPushService;
     @Autowired
     private IMovieRankPushService movieRankPushService;
+    @Autowired
+    private IFeishuDocSyncService feishuDocSyncService;
 
     @Autowired
     IUserLoginRecordService userLoginRecordService;
@@ -80,10 +82,16 @@ public class FeishuController {
 //            cpsReportService.runCPSSettlementData(date);
 //            System.out.println("\n\n");
 //        }
-
 //        distributionPushService.sendToday();
 //        distributionPushService.sendYesterday();
-        movieRankPushService.send();
+//        movieRankPushService.send();
+
+//        bytedanceProductUpdateService.pullFanqiePlaylet();
+
+
+//        bytedanceProductUpdateService.runDysDistribute();
+//        bytedanceProductUpdateService.clearAuditFailProduct();
+//        feishuDocSyncService.syncBytedanceDysDistributeMovies();
     }
 
 

+ 7 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/entity/AigcProductAlbum.java

@@ -36,4 +36,11 @@ public class AigcProductAlbum {
     private Integer startingUnlockEpisode;
 
     private Integer source;
+
+    private String albumLink;
+    private String playletId;
+    private String playletPurchasePanelId;
+    private String businessMethod;
+
+    private String productId;
 }

+ 3 - 1
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/entity/AigcProductPlatform.java

@@ -7,7 +7,7 @@ public class AigcProductPlatform {
     private String platformId;//商品库ID
     private String advertiserId;//所属主账户ID
     private Integer type;//商品库类型 1:免费 2:付费
-    private Integer platformType;//商品库定位分类 1:抖音小程序(+微信小程序) 2:仅微信小程序
+    private Integer platformType;//商品库定位分类 1:抖音小程序(+微信小程序) 2:仅微信小程序 3:端原生
     private String platformName;//商品库名称
     private String miniInstanceId;//字节小程序实例ID
     private String updateTime;//更新时间
@@ -29,5 +29,7 @@ public class AigcProductPlatform {
 
     private String miniAppAdvertiserId;//小程序主账户ID
 
+    private String copyrightOwner;
+
 
 }

+ 10 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/BytedanceProductUpdateMapper.java

@@ -19,6 +19,11 @@ public interface BytedanceProductUpdateMapper {
     List<AigcProductAlbum> getIAAVideoList();
     List<JSONObject> getIAAProductTypeEnums();
 
+
+    List<AigcProductPlatform> getDysIaaPlatformList();
+    List<AigcProductAlbum> getDysDistributorVideo(@Param("businessMethod") String businessMethod);
+    List<String> randomFanqieMovieImgs(@Param("count") Integer count);
+
     int updateInstanceId(@Param("advertiserId") String advertiserId, @Param("instanceId") String instanceId, @Param("source") Integer source);
 
     JSONObject getVideoInfo(@Param("videoId") Long videoId);
@@ -42,4 +47,9 @@ public interface BytedanceProductUpdateMapper {
 
     int updateMovieAuthStatus(@Param("platformId") String platformId);
 
+
+    int batchInsertFanqiePlayletInfo(@Param("list") List<JSONObject> list);
+
+    int batchInsertDysDistributePlayletInfo(List<AigcProductAlbum> list);
+
 }

+ 2 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/BytedancePromoterReportMapper.java

@@ -19,6 +19,8 @@ public interface BytedancePromoterReportMapper {
 
     void deleteInfoByErrorId(@Param("errorId") Long errorId);
 
+    void updateStatusByErrorId(@Param("errorId") Long errorId);
+
     void replacePromoterReportDailies(@Param("list") List<BytedancePromoterReportDaily> promoterReportDailies);
     @DS("sd_group_commit")
     void replacePromoterReportDailiesSD(@Param("list") List<BytedancePromoterReportDaily> promoterReportDailies);

+ 51 - 4
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/xml/BytedanceProductUpdateMapper.xml

@@ -25,28 +25,32 @@
 
 
     <select id="getIAPPlatformList" resultType="cn.com.ctop.job.bytedance.data.entity.AigcProductPlatform">
-        select t1.platform_id, t1.advertiser_id, t1.type, t1.platform_type, t1.platform_name, t1.mini_instance_id, t1.update_time, t1.create_time, t1.mi_appid, t1.membership_types, t1.max_charge, t1.min_charge, t1.recommended_charge, t1.single_price, t1._status, t1.social_credit_code, t1.movie_auth_status, t1.is_bytedance, t1.is_wechat, t1.is_dys, t1.source, ifnull(t1.mini_app_advertiser_id,t1.advertiser_id) as mini_app_advertiser_id, t3.access_token
+        select t1.platform_id, t1.advertiser_id, t1.type, t1.platform_type, t1.platform_name, t1.mini_instance_id, t1.update_time, t1.create_time, t1.mi_appid, t1.membership_types, t1.max_charge, t1.min_charge, t1.recommended_charge, t1.single_price, t1._status, t1.social_credit_code, t1.movie_auth_status, t1.is_bytedance, t1.is_wechat, t1.is_dys, t1.source, ifnull(t1.mini_app_advertiser_id,t1.advertiser_id) as mini_app_advertiser_id, t3.access_token,
+        '天津星链视界信息技术有限公司' as copyright_owner
         FROM deepthink.bytedance_product_main_advertiser t1
                  left join deepthink.bytedance_advertiser_list t2 on t1.advertiser_id=t2.advertiser_id
                  left join deepthink.bytedance_auth_list t3 on t2.admin_advertiser_id=t3.admin_advertiser_id
         where t1.`type`=2 and t1.`_status`=0 and platform_type=1 and t1.mini_instance_id is not null
     </select>
     <select id="getIAPPlatformInitList" resultType="cn.com.ctop.job.bytedance.data.entity.AigcProductPlatform">
-        select t1.platform_id, t1.advertiser_id, t1.type, t1.platform_type, t1.platform_name, t1.mini_instance_id, t1.update_time, t1.create_time, t1.mi_appid, t1.membership_types, t1.max_charge, t1.min_charge, t1.recommended_charge, t1.single_price, t1._status, t1.social_credit_code, t1.movie_auth_status, t1.is_bytedance, t1.is_wechat, t1.is_dys, t1.source, ifnull(t1.mini_app_advertiser_id,t1.advertiser_id) as mini_app_advertiser_id, t3.access_token
+        select t1.platform_id, t1.advertiser_id, t1.type, t1.platform_type, t1.platform_name, t1.mini_instance_id, t1.update_time, t1.create_time, t1.mi_appid, t1.membership_types, t1.max_charge, t1.min_charge, t1.recommended_charge, t1.single_price, t1._status, t1.social_credit_code, t1.movie_auth_status, t1.is_bytedance, t1.is_wechat, t1.is_dys, t1.source, ifnull(t1.mini_app_advertiser_id,t1.advertiser_id) as mini_app_advertiser_id, t3.access_token,
+               '天津星链视界信息技术有限公司' as copyright_owner
         FROM deepthink.bytedance_product_main_advertiser t1
         left join deepthink.bytedance_advertiser_list t2 on t1.advertiser_id=t2.advertiser_id
         left join deepthink.bytedance_auth_list t3 on t2.admin_advertiser_id=t3.admin_advertiser_id
         where t1.`type`=2 and t1.`_status`=0 and platform_type=1
     </select>
     <select id="getIAAPlatformList" resultType="cn.com.ctop.job.bytedance.data.entity.AigcProductPlatform">
-        select t1.platform_id, t1.advertiser_id, t1.type, t1.platform_type, t1.platform_name, t1.mini_instance_id, t1.update_time, t1.create_time, t1.mi_appid, t1.membership_types, t1.max_charge, t1.min_charge, t1.recommended_charge, t1.single_price, t1._status, t1.social_credit_code, t1.movie_auth_status, t1.is_bytedance, t1.is_wechat, t1.is_dys, t1.source, ifnull(t1.mini_app_advertiser_id,t1.advertiser_id) as mini_app_advertiser_id, t3.access_token
+        select t1.platform_id, t1.advertiser_id, t1.type, t1.platform_type, t1.platform_name, t1.mini_instance_id, t1.update_time, t1.create_time, t1.mi_appid, t1.membership_types, t1.max_charge, t1.min_charge, t1.recommended_charge, t1.single_price, t1._status, t1.social_credit_code, t1.movie_auth_status, t1.is_bytedance, t1.is_wechat, t1.is_dys, t1.source, ifnull(t1.mini_app_advertiser_id,t1.advertiser_id) as mini_app_advertiser_id, t3.access_token,
+               '天津星链视界信息技术有限公司' as copyright_owner
         FROM deepthink.bytedance_product_main_advertiser t1
         left join deepthink.bytedance_advertiser_list t2 on t1.advertiser_id=t2.advertiser_id
         left join deepthink.bytedance_auth_list t3 on t2.admin_advertiser_id=t3.admin_advertiser_id
         where t1.`type`=1 and t1.`_status`=0 and platform_type=1 and t1.mini_instance_id is not null
     </select>
     <select id="getIAAPlatformInitList" resultType="cn.com.ctop.job.bytedance.data.entity.AigcProductPlatform">
-        select t1.platform_id, t1.advertiser_id, t1.type, t1.platform_type, t1.platform_name, t1.mini_instance_id, t1.update_time, t1.create_time, t1.mi_appid, t1.membership_types, t1.max_charge, t1.min_charge, t1.recommended_charge, t1.single_price, t1._status, t1.social_credit_code, t1.movie_auth_status, t1.is_bytedance, t1.is_wechat, t1.is_dys, t1.source, ifnull(t1.mini_app_advertiser_id,t1.advertiser_id) as mini_app_advertiser_id, t3.access_token
+        select t1.platform_id, t1.advertiser_id, t1.type, t1.platform_type, t1.platform_name, t1.mini_instance_id, t1.update_time, t1.create_time, t1.mi_appid, t1.membership_types, t1.max_charge, t1.min_charge, t1.recommended_charge, t1.single_price, t1._status, t1.social_credit_code, t1.movie_auth_status, t1.is_bytedance, t1.is_wechat, t1.is_dys, t1.source, ifnull(t1.mini_app_advertiser_id,t1.advertiser_id) as mini_app_advertiser_id, t3.access_token,
+               '天津星链视界信息技术有限公司' as copyright_owner
         FROM deepthink.bytedance_product_main_advertiser t1
         left join deepthink.bytedance_advertiser_list t2 on t1.advertiser_id=t2.advertiser_id
         left join deepthink.bytedance_auth_list t3 on t2.admin_advertiser_id=t3.admin_advertiser_id
@@ -124,4 +128,47 @@
         from deepthink.bytedance_product_main_advertiser
         where type=1 and _status=0 and movie_auth_status=0
     </select>
+    <select id="getDysDistributorVideo" resultType="cn.com.ctop.job.bytedance.data.entity.AigcProductAlbum">
+        select tb1.promote_link as albumLink,
+               3 as platformType,
+               tb1.movie_name as name,
+               3 as playletGender,
+               100 as playletNum,
+               1 as playletDuration,
+               10 as startingUnlockEpisode,
+               tb1.movie_source as source,
+               tb2.movie_url as img
+        from deepthink.dys_distribute_promote_link tb1
+        left join deepthink.changdu_movie_config tb2
+        on tb1.movie_source=24 and tb1.movie_name=tb2.movie_name
+        where tb1.business_method=#{businessMethod}
+    </select>
+    <select id="getDysIaaPlatformList" resultType="cn.com.ctop.job.bytedance.data.entity.AigcProductPlatform">
+        select t1.platform_id, t1.advertiser_id, t1.type, t1.platform_type, t1.platform_name, t1.mini_instance_id, t1.update_time, t1.create_time, t1.mi_appid, t1.membership_types, t1.max_charge, t1.min_charge, t1.recommended_charge, t1.single_price, t1._status, t1.social_credit_code, t1.movie_auth_status, t1.is_bytedance, t1.is_wechat, t1.is_dys, t1.source, ifnull(t1.mini_app_advertiser_id,t1.advertiser_id) as mini_app_advertiser_id, t3.access_token
+        FROM deepthink.bytedance_product_main_advertiser t1
+                 left join deepthink.bytedance_advertiser_list t2 on t1.advertiser_id=t2.advertiser_id
+                 left join deepthink.bytedance_auth_list t3 on t2.admin_advertiser_id=t3.admin_advertiser_id
+        where t1.`_status`=0 and platform_type=3 and t1.is_dys=1
+    </select>
+    <select id="randomFanqieMovieImgs" resultType="java.lang.String">
+        select movie_url
+        from deepthink.changdu_movie_config
+        limit #{count}
+    </select>
+    <insert id="batchInsertFanqiePlayletInfo" >
+        replace into deepthink.dys_distribute_promote_link
+        (playlet_id, playlet_purchase_panel_id, movie_name, promote_link, business_method, movie_source)
+        values
+        <foreach collection="list" item="item" separator=",">
+            (#{item.playletId}, #{item.playletPurchasePanelId}, #{item.movieName}, #{item.promoteLink}, 'IAA',24)
+        </foreach>
+    </insert>
+    <insert id="batchInsertDysDistributePlayletInfo">
+        replace into deepthink.dys_distribute_promote_link
+        (playlet_id, playlet_purchase_panel_id, movie_name, promote_link, business_method, movie_source)
+        values
+        <foreach collection="list" item="item" separator=",">
+            (#{item.playletId}, #{item.playletPurchasePanelId}, #{item.name}, #{item.albumLink}, #{item.businessMethod}, #{item.source})
+        </foreach>
+    </insert>
 </mapper>

+ 6 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/xml/BytedancePromoterReportMapper.xml

@@ -1,6 +1,11 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
 <mapper namespace="cn.com.ctop.job.bytedance.data.mapper.BytedancePromoterReportMapper">
+    <update id="updateStatusByErrorId">
+        update bytedance_error_log
+        set error_status = 1
+        WHERE id = #{errorId}
+    </update>
     <delete id="deleteInfoByErrorId">
         DELETE
         FROM bytedance_error_log
@@ -12,6 +17,7 @@
         FROM bytedance_error_log t1
                  LEFT JOIN deepthink.bytedance_advertiser_list t2 ON t1.advertiser_id = t2.advertiser_id
                  LEFT JOIN deepthink.bytedance_auth_list t3 ON t2.admin_advertiser_id = t3.admin_advertiser_id
+        where t1.error_status = 0 or t1.update_time &lt;= date_add(now(),interval -1 hour )
     </select>
 
     <select id="getListBydate" resultType="com.alibaba.fastjson.JSONObject" parameterType="java.lang.Integer">

+ 17 - 5
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/xml/ReportsAdPushMapper.xml

@@ -185,7 +185,16 @@
     <select id="todayTopMovie" resultType="com.alibaba.fastjson.JSONObject" >
         select
         tb4.standard_movie_name as movie_name, tb4.movie_project_source, tb6.dict_name as movie_project_source_name,
-        group_concat(distinct case tb4.movie_source when 2 then '2' else '1' end) as movie_source,
+        case
+        when (DATEDIFF(STR_TO_DATE(tb1.stat_date, '%Y%m%d'), STR_TO_DATE(tb4.project_ad_date, '%Y%m%d')) + 1) between 1
+        and 3 then '新剧1阶'
+        when (DATEDIFF(STR_TO_DATE(tb1.stat_date, '%Y%m%d'), STR_TO_DATE(tb4.project_ad_date, '%Y%m%d')) + 1) between 4
+        and 7 then '新剧2阶'
+        when (DATEDIFF(STR_TO_DATE(tb1.stat_date, '%Y%m%d'), STR_TO_DATE(tb4.project_ad_date, '%Y%m%d')) + 1) between 8
+        and 15 then '次新剧'
+        when (DATEDIFF(STR_TO_DATE(tb1.stat_date, '%Y%m%d'), STR_TO_DATE(tb4.project_ad_date, '%Y%m%d')) + 1) >=15 then
+        '老剧'
+        else 999 end as project_ad_step,
         <include refid="endAmount"/>,
         <include refid="waterEndAmount"/>,
         <include refid="costAmount"/>,
@@ -196,8 +205,8 @@
         <include refid="shareIaaAmount3"/>,
         round(ifnull(sum(hour_cost_amount), 0), 2) as hour_cost_amount
         from
-        (select movie_id from application.media_ad_report_daily where stat_date=${date} and ma_appid in (select app_id from tidb.deepthink.mini_app_info where business_type not in (2,4,6))
-        union select movie_id from application.user_data_report_daily where stat_date=${date} and ma_appid in (select app_id from tidb.deepthink.mini_app_info where business_type not in (2,4,6))) tb1
+        (select ${date} as stat_date, movie_id from application.media_ad_report_daily where stat_date=${date} and ma_appid in (select app_id from tidb.deepthink.mini_app_info where business_type not in (2,4,6))
+        union select ${date} as stat_date, movie_id from application.user_data_report_daily where stat_date=${date} and ma_appid in (select app_id from tidb.deepthink.mini_app_info where business_type not in (2,4,6))) tb1
         left join
         (
         select movie_id, sum(iaa_cost_amount) as iaa_cost_amount, sum(iaa_real_cost_amount) as iaa_real_cost_amount,
@@ -223,7 +232,7 @@
         group by movie_id
         ) tb3 on tb1.movie_id=tb3.movie_id
         left join
-        (select moive_id, standard_movie_id, standard_movie_name, movie_source, movie_project_source from tidb.deepthink.all_moive
+        (select moive_id, standard_movie_id, standard_movie_name, movie_source, movie_project_source,project_ad_date from tidb.deepthink.all_moive
         ) tb4 on tb1.movie_id=tb4.moive_id
         left join
         (select movie_id, ifnull(sum(cost_amount), 0) as hour_cost_amount from application.media_ad_report_hourly
@@ -233,7 +242,7 @@
         (select dict_key, dict_name from tidb.deepthink.dt_dictionary where select_key='movie_project_source'
         ) tb6 on tb4.movie_project_source=tb6.dict_key
         where 1=1 and tb1.movie_id != '-9999'
-        group by tb4.standard_movie_name, tb4.movie_project_source, tb6.dict_name
+        group by 1,2,3,4
         order by end_amount desc
         limit 20
     </select>
@@ -280,6 +289,7 @@
             select dept_id, dept_name, dept_id as sub_dept_id, dept_name as sub_dept_name from tidb.deepthink.sys_dept where parent_id in (select dept_id from tidb.deepthink.sys_dept where parent_id=300)
         ) tb5
         on tb4.dept_id = tb5.sub_dept_id
+        where tb1.user_id is not null
         group by tb1.user_id, tb4.phonenumber, tb4.nick_name, tb5.dept_id, tb5.dept_name
         having sum(cost_amount)>1
         order by rk asc
@@ -369,6 +379,7 @@
         select dept_id, dept_name, dept_id as sub_dept_id, dept_name as sub_dept_name from tidb.deepthink.sys_dept where parent_id in (select dept_id from tidb.deepthink.sys_dept where parent_id=300)
         ) tb5
         on tb4.dept_id = tb5.sub_dept_id
+        where tb1.user_id is not null
         group by tb5.dept_id, tb5.dept_name
         having sum(cost_amount)>1
         order by rk asc
@@ -523,6 +534,7 @@
         <include refid="shareIaaAmount"/>,
         <include refid="realProfit"/>,
         <include refid="waterProfit"/>,
+        <include refid="waterEndAmount"/>,
         <include refid="endAmount"/>,
         date_format(max(update_time), '%Y-%m-%d %H:%i:%s') as update_time
         from

+ 7 - 1
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/IBytedanceProductUpdateService.java

@@ -4,7 +4,9 @@ import java.io.IOException;
 
 public interface IBytedanceProductUpdateService {
 
-    void run() throws Exception;
+    void runMp() throws Exception;
+
+    void runDysDistribute() throws IOException;
 
     void authMovieResource();
 
@@ -16,4 +18,8 @@ public interface IBytedanceProductUpdateService {
     void uploadAlbum() throws IOException;
 
     void refreshAlbumStatus() throws IOException;
+
+    void pullFanqiePlaylet();
+
+    void clearAuditFailProduct();
 }

+ 17 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/IFeishuDocSyncService.java

@@ -0,0 +1,17 @@
+package cn.com.ctop.job.bytedance.data.service;
+
+public interface IFeishuDocSyncService {
+
+    /**
+     * 同步巨量 IAA 商品库
+     */
+    void syncBytedanceIaaProductPlatform();
+    /**
+     * 同步巨量 IAP 商品库
+     */
+    void syncBytedanceIapProductPlatform();
+    /**
+     * 同步巨量 端原生分销剧目
+     */
+    void syncBytedanceDysDistributeMovies();
+}

+ 2 - 4
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedanceCdpProjectServiceImpl.java

@@ -152,8 +152,7 @@ public class BytedanceCdpProjectServiceImpl implements IBytedanceCdpProjectServi
                             log.info("---账户({})广告更新成功", advertiserId);
                     }*/
                 } else {
-                    //40100请求超频 (40100 == code || 40110 == code || 40130 == code) &&
-                    if (count <= 5) {
+                    if (count <= 5 && code != 40110) {
                         Thread.sleep(800);
                         getPromotionListVo(advertiserId, ids, date, page, cursor, count + 1, errorId, isLog);
                     } else {
@@ -248,8 +247,7 @@ public class BytedanceCdpProjectServiceImpl implements IBytedanceCdpProjectServi
                             log.info("---账户({})项目信息更新成功", advertiserId);
                     }
                 } else {
-                    //40100请求超频 (40100 == code || 40110 == code || 40130 == code) &&
-                    if (count <= 5) {
+                    if (count <= 5 && code != 40110) {
                         Thread.sleep(800);
                         getProjectListVo(advertiserId, ids, type, date, page, count + 1, errorId, isLog);
                     } else {

+ 8 - 3
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedanceMaterialReportServiceImpl.java

@@ -2,6 +2,7 @@ package cn.com.ctop.job.bytedance.data.service.impl;
 
 import cn.com.ctop.job.bytedance.data.entity.BytedanceErrorLog;
 import cn.com.ctop.job.bytedance.data.mapper.BytedancePromoterReportMapper;
+import cn.com.ctop.job.bytedance.data.mapper.BytedanceRefreshTokenMapper;
 import cn.com.ctop.job.bytedance.data.service.IBytedanceMaterialReportService;
 import cn.com.ctop.job.bytedance.data.utils.AlertUtils;
 import cn.com.ctop.job.bytedance.data.utils.Check;
@@ -29,11 +30,14 @@ public class BytedanceMaterialReportServiceImpl implements IBytedanceMaterialRep
     @Autowired
     private DorisMultiTableStreamLoadManager dorisLoadManager;
     @Autowired
+    private BytedanceRefreshTokenMapper tokenMapper;
+    @Autowired
     private RedisTemplate redisTemplate_db2;
 
     @Override
     public void getBytedanceMaterialDailyReport(Long advertiserId, String accessToken, String startDate, String endDate, Integer page, Long errorId, Integer isLog, Integer isSend, int retry) {
         try {
+            accessToken = tokenMapper.onlyGetToken(advertiserId);
             String url = "https://api.oceanengine.com/open_api/v3.0/report/custom/get/";
             Map<String, Object> paramsMap = new HashMap<>();
             paramsMap.put("advertiser_id", advertiserId);
@@ -86,14 +90,14 @@ public class BytedanceMaterialReportServiceImpl implements IBytedanceMaterialRep
 
                             Long materialId = dimensionsJson.getLong("material_id");
                             String imageMode = dimensionsJson.getString("image_mode");
-                            if (!materialIds.contains(materialId) && !redisTemplate_db2.hasKey("mvid:1:" + materialId) && imageMode.contains("视频")) {
+                            if (!materialIds.contains(materialId) && imageMode.contains("视频") && !redisTemplate_db2.hasKey("mvid:1:" + materialId)) {
                                 materialIds.add(materialId);
                             }
                         }
                     }
                 }
             } else {
-                if (retry <= 5) {
+                if (retry <= 5 && code != 40110) {
                     try {
                         Thread.sleep(800);
                     } catch (Exception ignored) {
@@ -138,6 +142,7 @@ public class BytedanceMaterialReportServiceImpl implements IBytedanceMaterialRep
 
     public void getBytedanceMaterialVideo(Long advertiserId, Set<Long> materialIds, String accessToken, String startTime, String endTime, Integer page, Long errorId, Integer isLog, Integer isSend, int retry) {
         try {
+            accessToken = tokenMapper.onlyGetToken(advertiserId);
             String url = "https://api.oceanengine.com/open_api/2/file/video/get/";
             Map<String, Object> paramsMap = new HashMap<>();
             paramsMap.put("advertiser_id", advertiserId);
@@ -189,7 +194,7 @@ public class BytedanceMaterialReportServiceImpl implements IBytedanceMaterialRep
                     }
                 }
             } else {
-                if (retry <= 5) {
+                if (retry <= 5 && code != 40110) {
                     try {
                         Thread.sleep(800);
                     } catch (Exception ignored) {

+ 4 - 1
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedanceMiniAppServiceImpl.java

@@ -143,6 +143,7 @@ public class BytedanceMiniAppServiceImpl implements IBytedanceMiniAppService {
                     JSONArray content = new JSONArray();
                     if (!Check.isNull(jsonObject)) {
                         Integer code = jsonObject.getInteger("err_no");
+                        String errMsg = jsonObject.getString("err_msg");
                         if (code == 0) {
                             JSONObject data = jsonObject.getJSONObject("data");
 
@@ -164,7 +165,9 @@ public class BytedanceMiniAppServiceImpl implements IBytedanceMiniAppService {
                             }
                         } else {
                             log.error("[{}]抖小ma_ecpm拉取失败{}~{},返回信息:{}", appId, startEventTime, endEventTime, s);
-                            insertErrorLog(isLog, startEventTime, endTime, "ma_ecpm:" + appId, "daily", s);
+                            if (errMsg == null || !errMsg.contains("access_token")) {
+                                insertErrorLog(isLog, startEventTime, endTime, "ma_ecpm:" + appId, "daily", s);
+                            }
                             return;
                         }
                     } else {

+ 335 - 21
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedanceProductUpdateServiceImpl.java

@@ -6,14 +6,17 @@ import cn.com.ctop.job.bytedance.data.mapper.BytedanceProductUpdateMapper;
 import cn.com.ctop.job.bytedance.data.service.IBytedanceProductUpdateService;
 import cn.com.ctop.job.bytedance.data.utils.Check;
 import cn.com.ctop.job.bytedance.data.utils.HttpUtils;
+import cn.com.ctop.job.bytedance.utils.BytedanceProductDocProperties;
 import cn.com.ctop.job.bytedance.utils.FeishuRobotUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
+import org.springframework.web.util.UriComponentsBuilder;
 
 import javax.annotation.Resource;
 import java.io.IOException;
@@ -26,6 +29,9 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
     BytedanceProductUpdateMapper bytedanceProductUpdateMapper;
     @Resource
     private RedisTemplate redis2Template_db5;
+    @Autowired
+    BytedanceProductDocProperties productDocProperties;
+
 
     public static final String DOUYIN_MOVIE_SOURCE_APP="ttd652a0ef496310bd01";
 
@@ -40,7 +46,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
     public static final String HOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/92e2445e-76df-44fb-8f61-f55ac94f49bd";
 
     @Override
-    public void run() throws Exception {
+    public void runMp() throws Exception {
         Set<String> errors = new HashSet<>();
         log.info("付费商品库更新中...");
         List<AigcProductPlatform> iapPlatformList = bytedanceProductUpdateMapper.getIAPPlatformList(); //商品库列表
@@ -51,7 +57,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
                 obj -> obj,
                 (existing, replacement) -> replacement
         ));
-        runProductTask(iapPlatformList, iapVideoList, iapProductTypeMap, errors, BusinessType.IAP);
+        runMpProductTask(iapPlatformList, iapVideoList, iapProductTypeMap, errors, BusinessType.IAP);
         log.info("付费商品库更新完成");
 
 
@@ -65,7 +71,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
                 obj -> obj,
                 (existing, replacement) -> replacement
         ));
-        runProductTask(iaaPlatformList, iaaVideoList, iaaProductTypeMap, errors, BusinessType.IAA);
+        runMpProductTask(iaaPlatformList, iaaVideoList, iaaProductTypeMap, errors, BusinessType.IAA);
         log.info("免费商品库更新完成");
 
 
@@ -78,10 +84,43 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
         }
     }
 
-    private void runProductTask(List<AigcProductPlatform> platformList, List<AigcProductAlbum> albums, Map<String, JSONObject> productTypeMap, Set<String> errors, BusinessType businessType) throws IOException {
+    @Override
+    public void runDysDistribute() throws IOException {
+        Set<String> errors = new HashSet<>();
+        List<AigcProductPlatform> iaaPlatformList = bytedanceProductUpdateMapper.getDysIaaPlatformList(); //商品库列表
+        Map<String, String> sourceCopywriteOwner = new HashMap<>();
+        for (BytedanceProductDocProperties.DysDistributorLinkTable table : productDocProperties.getDysMovies()){
+            sourceCopywriteOwner.put(table.getMovieSource(), table.getCopyrightOwner());
+        }
+        iaaPlatformList.forEach(p -> {
+            p.setCopyrightOwner(sourceCopywriteOwner.get(String.valueOf(p.getSource())));
+        });
+
+        List<AigcProductAlbum> iaaVideos = bytedanceProductUpdateMapper.getDysDistributorVideo("IAA");
+        iaaVideos.forEach(v -> {
+            v.setPlayletId(getQueryParam(v.getAlbumLink(), "playlet_id"));
+            if (StringUtils.isEmpty(v.getImg())){
+                v.setImg("https://oss.artlinkworld.cn/imgsource/20251110-144804.png");//兜底
+            }
+        });
+
+        runDysProductTask(iaaPlatformList, iaaVideos, new HashMap<>(), errors, BusinessType.IAA);
+        System.out.println("端原生分销商品库更新完成");
+
+        errors.removeIf(s -> s.contains("剧目不可用"));
+        if (!Check.isNull(errors)){
+            List<String> info = new ArrayList<>();
+            info.add("端原生分销商品上传报错通知");
+            info.addAll(errors);
+            FeishuRobotUtil.sendTextToWebhook(StringUtils.join(info, "\n"), HOOK_URL);
+        }
+    }
+
+    private void runMpProductTask(List<AigcProductPlatform> platformList, List<AigcProductAlbum> albums, Map<String, JSONObject> productTypeMap, Set<String> errors, BusinessType businessType) throws IOException {
         for (AigcProductPlatform platform : platformList){
             // 拉取已上传剧目,对比,得到未上传剧目列表
-            List<String> hasUpload = hasUploadProductList(platform);
+            List<AigcProductAlbum> hasUploadProductList = hasUploadProductList(platform);
+            List<String> hasUpload = hasUploadProductList.stream().map(AigcProductAlbum::getProductId).collect(Collectors.toList());
             System.out.println("已上传剧目数: "+hasUpload.size() + ", 商品库ID: "+platform.getPlatformId()+", 来源:"+platform.getSource());
             List<AigcProductAlbum> toUpload = albums.stream()
                     .filter(o -> Objects.equals(o.getSource(), platform.getSource()))
@@ -121,16 +160,49 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
         }
     }
 
+
+    private void runDysProductTask(List<AigcProductPlatform> platformList, List<AigcProductAlbum> albums, Map<String, JSONObject> productTypeMap, Set<String> errors, BusinessType businessType) throws IOException {
+        for (AigcProductPlatform platform : platformList){
+            // 拉取已上传剧目,对比,得到未上传剧目列表
+            List<AigcProductAlbum> hasUploadAlbums = hasUploadProductList(platform);
+            List<String> hasUploadPlayletIds = hasUploadAlbums.stream().map(AigcProductAlbum::getPlayletId).collect(Collectors.toList());
+//            System.out.println("已上传剧目数: "+hasUpload.size() + ", 商品库ID: "+platform.getPlatformId()+", 来源:"+platform.getSource());
+            List<AigcProductAlbum> toUpload = albums.stream()
+                    .filter(o -> !hasUploadPlayletIds.contains(o.getPlayletId()))
+                    .filter(o -> Objects.equals(o.getPlatformType(), String.valueOf(platform.getPlatformType())))
+                    .filter(o -> Objects.equals(o.getSource(), platform.getSource()))
+                    // 根据link里的参数过滤已上传的
+                    .collect(Collectors.toList());
+            System.out.println("待上传剧目数: "+toUpload.size() + ", 商品库ID: "+platform.getPlatformId()+", 来源:"+platform.getSource());
+
+//            if (1==1){
+//                return;
+//            }
+            if (toUpload.isEmpty()){
+                continue;
+            }
+
+            //未上传剧目:对比平台类型;确定商品分类;获取推广链接
+            for (AigcProductAlbum album : toUpload){
+                JSONObject defaultTheme = JSONObject.parseObject("{\"first_type_id\":\"2038\",\"first_type_name\":\"单剧目-短剧\",\"second_type_id\":\"203807\",\"second_type_name\":\"其他剧情\",\"third_type_name\":\"其他\",\"third_type_id\":\"20380701\"}");
+                uploadProduct(platform, album, null, errors, defaultTheme, businessType);
+//                try {
+//                    Thread.sleep(80);
+//                }catch (InterruptedException ignored){}
+            }
+        }
+    }
+
     /**
      * 当前商品库中,已经上传的商品列表
      * @param platform
      * @return
      */
-    private List<String> hasUploadProductList(AigcProductPlatform platform){
-        return hasUploadProductPageList(platform, 1, 100);
+    private List<AigcProductAlbum> hasUploadProductList(AigcProductPlatform platform){
+        return hasUploadProductPageList(platform, 1, 100, null);
     }
 
-    private List<String> hasUploadProductPageList(AigcProductPlatform platform, int page, int pageSize){
+    private List<AigcProductAlbum> hasUploadProductPageList(AigcProductPlatform platform, int page, int pageSize, Integer auditStatus){
         String url = "https://api.oceanengine.com/open_api/2/dpa/detail/get/";
         Map<String, String> headers = new HashMap<>();
         headers.put("Access-Token", platform.getAccessToken());
@@ -139,6 +211,13 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
         params.put("product_platform_id", Long.valueOf(platform.getPlatformId()));
         params.put("page", String.valueOf(page));
         params.put("page_size", String.valueOf(pageSize));
+        JSONObject filtering = new JSONObject();
+        if (auditStatus != null){
+            filtering.put("audit_status", auditStatus);
+        }
+        if (!filtering.isEmpty()){
+            params.put("filtering", filtering);
+        }
         String res = HttpUtils.httpGet(url, params, headers);
         if (res == null || res.isEmpty()) {
             System.out.println("获取已上传商品列表失败, 广告账号ID:" + platform.getAdvertiserId() + ", 商品库ID:" + platform.getPlatformId());
@@ -154,16 +233,24 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
                 if (list == null || list.isEmpty()){
                     return new ArrayList<>();
                 }
-                List<String> resList = new ArrayList<>(list.size());
+                List<AigcProductAlbum> resList = new ArrayList<>(list.size());
                 for (int i = 0; i < list.size(); i++) {
                     JSONObject obj = list.getJSONObject(i);
-                    resList.add(String.valueOf(obj.getLongValue("product_id")));
+                    AigcProductAlbum album = new AigcProductAlbum();
+                    album.setProductId(String.valueOf(obj.getLongValue("product_id")));
+                    album.setName(obj.getString("name"));
+                    JSONObject profession = obj.getJSONObject("profession");
+                    if (profession!=null && profession.containsKey("album_link")){
+                        album.setAlbumLink(profession.getString("album_link"));
+                        album.setPlayletId(getQueryParam(album.getAlbumLink(), "playlet_id"));
+                    }
+                    resList.add(album);
                 }
                 JSONObject page_info = jsonObject.getJSONObject("data").getJSONObject("page_info");
                 int total_page = page_info.getIntValue("total_page");
                 if (total_page > page){
                     //递归获取下一页
-                    List<String> nextPage = hasUploadProductPageList(platform, page + 1, pageSize);
+                    List<AigcProductAlbum> nextPage = hasUploadProductPageList(platform, page + 1, pageSize, auditStatus);
                     resList.addAll(nextPage);
                 }
                 return resList;
@@ -299,14 +386,21 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
     private void uploadProduct(AigcProductPlatform platform, AigcProductAlbum album,
                                   String schemaLink, Set<String> errorBlanket, JSONObject productType,
                               BusinessType businessType){
-        String url = "https://ad.oceanengine.com/open_api/2/dpa/product/update/";
+        String url;
+        if (StringUtils.isEmpty(album.getAlbumId())){
+            url = "https://ad.oceanengine.com/open_api/2/dpa/product/create/";
+        }else {
+            url = "https://ad.oceanengine.com/open_api/2/dpa/product/update/";
+        }
         Map<String, String> headers = new HashMap<>();
         headers.put("Access-Token", platform.getAccessToken());
         headers.put("Content-Type", "application/json");
 
         JSONObject request = new JSONObject();
         String album_id = album.getAlbumId();
-        request.put("product_id", Long.valueOf(album_id));
+        if (StringUtils.isNotEmpty(album_id)){
+            request.put("product_id", Long.valueOf(album_id));
+        }
         JSONObject product_info = new JSONObject();
         product_info.put("name", album.getName());
         product_info.put("image_url", album.getImg());
@@ -321,7 +415,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
         request.put("advertiser_id", Long.valueOf(platform.getAdvertiserId()));
         request.put("platform_id", Long.valueOf(platform.getPlatformId()));
         JSONObject profession = new JSONObject();
-        profession.put("copyright_owner", album.getCopyrightOwner());
+        profession.put("copyright_owner", platform.getCopyrightOwner());
         profession.put("playlet_gender", "3");
         profession.put("playlet_num", String.valueOf(album.getPlayletNum()));
         profession.put("playlet_duration", album.getPlayletDuration());
@@ -363,8 +457,10 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
         }
         if (platform.getIsBytedance() == 1){
             profession.put("micro_app_link", schemaLink);
-        }else {
+        }else if (platform.getIsWechat() == 1){
             profession.put("album_id", album_id);
+        }else if (platform.getIsDys() == 1){
+            profession.put("album_link", album.getAlbumLink());
         }
         profession.put("ad_carrier", JSON.toJSONString(ad_carrier));
         product_info.put("profession", profession);
@@ -374,13 +470,28 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
 //        System.out.println("请求地址:" + url);
 //        System.out.println("请求头:" + headers);
 //        System.out.println("请求参数:" + request.toJSONString());
-        String res = HttpUtils.httpPostRequest(url, request, headers);
-        JSONObject btRes = JSONObject.parseObject(res);
-        int code = btRes.getIntValue("code");
-        if (code != 0){
-            String payName = businessType==BusinessType.IAP?"付费":"免费";
-            errorBlanket.add("上传"+payName+"商品失败,code: " + code + ", msg: " + btRes.getString("message")+", 关联剧目: " + album.getName());
+        //重试3次
+        for (int retry = 0; retry < 3; retry++) {
+            String res = HttpUtils.httpPostRequest(url, request, headers);
+            JSONObject btRes = JSONObject.parseObject(res);
+            int code = btRes.getIntValue("code");
+            if (code != 0){
+                String errorMessage = btRes.getString("message");
+                if (errorMessage.contains("系统请求频率超限") && retry < 2){
+                    try {
+                        Thread.sleep(100);
+                    }catch (InterruptedException ignored){}
+                    continue;
+                }else {
+                    String payName = businessType==BusinessType.IAP?"付费":"免费";
+                    errorBlanket.add("上传"+payName+"商品失败,code: [" + code + "], msg: [" + errorMessage +"], 关联剧目: " + album.getName());
+                    break;
+                }
+            }else {
+                break;
+            }
         }
+
     }
 
     /**
@@ -647,6 +758,202 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
     }
 
 
+    public static final String FEISHU_EXCEL_TOKEN = "HGZYw1YKRiidYgkpzRocokyPnUd";
+    public static final String FEISHU_EXCEL_SHEETID = "add053";
+    public static final String FEISHU_EXCEL_OLD_SHEETID = "krjaDd";
+    @Override
+    public void pullFanqiePlaylet() {
+        String userToken = "u-eQOevKV793.WrHbW0yAQVl517s14h0UhjG20g1OGyx6u";
+        int startRow = 2;
+        int batchSize = 100;
+        int endRow = startRow + batchSize - 1;
+
+        while(!pullFanqieNewPlayletSheet(null, userToken, startRow, endRow)){
+            startRow = endRow + 1;
+            endRow = startRow + batchSize - 1;
+        }
+
+        while(!pullFanqieOldPlayletSheet(null, userToken, startRow, endRow)){
+            startRow = endRow + 1;
+            endRow = startRow + batchSize - 1;
+        }
+
+    }
+
+    @Override
+    public void clearAuditFailProduct() {
+        List<AigcProductPlatform> iaaPlatformList = bytedanceProductUpdateMapper.getDysIaaPlatformList(); //商品库列表
+        for (AigcProductPlatform platform : iaaPlatformList){
+            List<AigcProductAlbum> albums = hasUploadProductPageList(platform, 1, 100, 2); //审核失败的商品列表
+//            albums = albums.stream().filter(al -> StringUtils.isEmpty(al.getName())).collect(Collectors.toList());
+//            System.out.println(albums);
+//            if (1==1){
+//                return;
+//            }
+            if (Check.isNull(albums)) {
+                continue;
+            }
+            //删除审核失败的商品
+            for (AigcProductAlbum album : albums){
+                String url = "https://ad.oceanengine.com/open_api/2/dpa/product/delete/";
+                Map<String, String> headers = new HashMap<>();
+                headers.put("Access-Token", platform.getAccessToken());
+                Map<String, Object> params = new HashMap<>();
+                params.put("advertiser_id", Long.valueOf(platform.getAdvertiserId()));
+                params.put("platform_id", Long.valueOf(platform.getPlatformId()));
+                params.put("product_id", Long.valueOf(album.getProductId()));
+                String res = HttpUtils.httpPostRequest(url, params, headers);
+                if (res == null || res.isEmpty()){
+                    System.out.println("删除审核失败商品失败, 广告账号ID:" + platform.getAdvertiserId() + ", 商品库ID:" + platform.getPlatformId() + ", 商品ID:" + album.getProductId());
+                }else {
+                    JSONObject jsonObject = JSONObject.parseObject(res);
+                    int code = jsonObject.getIntValue("code");
+                    if (code != 0) {
+                        System.out.println("删除审核失败商品失败,code: " + code + ", msg: " + jsonObject.getString("message") + ", 广告账号ID:" + platform.getAdvertiserId() + ", 商品库ID:" + platform.getPlatformId() + ", 商品ID:" + album.getProductId());
+                    }else {
+                        System.out.println("删除审核失败商品成功,广告账号ID:" + platform.getAdvertiserId() + ", 商品库ID:" + platform.getPlatformId() + ", 商品ID:" + album.getProductId());
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @param tenantToken 当前页签token
+     * @param userToken 用户token
+     * @param startRow 起始行
+     * @param endRow 结束行
+     * @return
+     */
+    private boolean pullFanqieNewPlayletSheet(String tenantToken, String userToken,
+                                        int startRow,
+                                        int endRow){
+        String url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheetToken}/values_batch_get?ranges={ranges}";
+        url = url.replace("{spreadsheetToken}", FEISHU_EXCEL_TOKEN);
+        String ranges = FEISHU_EXCEL_SHEETID + "!A" + startRow + ":D" + endRow;
+        url = url.replace("{ranges}", ranges);
+
+        Map<String, String> headers = new HashMap<>();
+        headers.put("Authorization", "Bearer " + userToken);
+
+        String res = HttpUtils.httpGet(url, null, headers);
+        JSONObject resultObj = JSON.parseObject(res);
+        int code = resultObj.getIntValue("code");
+        boolean endFlag = false;
+        if (code != 0){
+            System.out.println("获取飞书表格数据失败,code: " + code + ", msg: " + resultObj.getString("msg"));
+            return true;
+        }else {
+            JSONObject data = resultObj.getJSONObject("data");
+            JSONObject valueRanges = data.getJSONArray("valueRanges").getJSONObject(0);
+            JSONArray values = valueRanges.getJSONArray("values");
+
+            List<JSONObject> insertList = new ArrayList<>();
+            for (int i = 0; i < values.size(); i++) {
+                JSONArray row = values.getJSONArray(i);
+                String r1 = row.getString(0);
+                String r2 = row.getString(1);
+                String r3 = row.getString(2);
+                String r4 = row.getString(3);
+                if (r1 == null && r2 == null && r3 == null && r4 == null){
+                    endFlag = true;
+                    break;
+                }
+                JSONObject obj = new JSONObject();
+                obj.put("movieName", r1);
+                obj.put("promoteLink", r4);
+
+                String[] urlParts = r4.split("\\?");
+                if (urlParts.length > 1){
+                    String[] queryParams = urlParts[1].split("&");
+                    for (String param : queryParams){
+                        String[] keyValue = param.split("=");
+                        if (keyValue.length == 2 && "playlet_id".equals(keyValue[0])) {
+                            obj.put("playletId", keyValue[1]);
+                        }
+                        if (keyValue.length == 2 && "playlet_purchase_panel_id".equals(keyValue[0])) {
+                            String purchasePanelId = keyValue[1];
+                            obj.put("playletPurchasePanelId", purchasePanelId);
+                            if ("0".equals(purchasePanelId)){
+                                obj.put("isPay", "0");
+                            }else {
+                                obj.put("isPay", "1");
+                            }
+                        }
+                    }
+                }
+                insertList.add(obj);
+            }
+            if (!insertList.isEmpty()){
+                bytedanceProductUpdateMapper.batchInsertFanqiePlayletInfo(insertList);
+            }
+            return endFlag;
+        }
+    }
+
+    /**
+     * @param tenantToken 当前页签token
+     * @param userToken 用户token
+     * @param startRow 起始行
+     * @param endRow 结束行
+     * @return
+     */
+    private boolean pullFanqieOldPlayletSheet(String tenantToken, String userToken,
+                                              int startRow,
+                                              int endRow){
+        String url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheetToken}/values_batch_get?ranges={ranges}";
+        url = url.replace("{spreadsheetToken}", FEISHU_EXCEL_TOKEN);
+        String ranges = FEISHU_EXCEL_OLD_SHEETID + "!A" + startRow + ":C" + endRow;
+        url = url.replace("{ranges}", ranges);
+
+        Map<String, String> headers = new HashMap<>();
+        headers.put("Authorization", "Bearer " + userToken);
+
+        String res = HttpUtils.httpGet(url, null, headers);
+        JSONObject resultObj = JSON.parseObject(res);
+        int code = resultObj.getIntValue("code");
+        boolean endFlag = false;
+        if (code != 0){
+            System.out.println("获取飞书表格数据失败,code: " + code + ", msg: " + resultObj.getString("msg"));
+            return true;
+        }else {
+            JSONObject data = resultObj.getJSONObject("data");
+            JSONObject valueRanges = data.getJSONArray("valueRanges").getJSONObject(0);
+            JSONArray values = valueRanges.getJSONArray("values");
+
+            List<JSONObject> insertList = new ArrayList<>();
+            for (int i = 0; i < values.size(); i++) {
+                JSONArray row = values.getJSONArray(i);
+                String r1 = row.getString(0);
+                String r2 = row.getString(1);
+                String r3 = row.getString(2);
+                if (r1 == null && r2 == null && r3 == null){
+                    endFlag = true;
+                    break;
+                }
+                JSONObject obj = new JSONObject();
+                obj.put("movieName", r1.replace("\\r", "").replace("\\n", ""));
+                String link = r3.replace("\\r", "").replace("\\n", "");
+                obj.put("promoteLink", link);
+                String playletId = getQueryParam(link, "playlet_id");
+                String purchasePanelId = getQueryParam(link, "playlet_purchase_panel_id");
+                obj.put("playletId", playletId);
+                obj.put("playletPurchasePanelId", purchasePanelId);
+                if ("0".equals(purchasePanelId)){
+                    obj.put("isPay", "0");
+                }else {
+                    obj.put("isPay", "1");
+                }
+                insertList.add(obj);
+            }
+            if (!insertList.isEmpty()){
+                bytedanceProductUpdateMapper.batchInsertFanqiePlayletInfo(insertList);
+            }
+            return endFlag;
+        }
+    }
+
+
     /**
      * 上传短剧
      * @param videoId from ly_videos
@@ -710,6 +1017,13 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
         }
     }
 
+    private static String getQueryParam(String url, String paramName){
+        return UriComponentsBuilder.fromUriString(url)
+                .build()
+                .getQueryParams()
+                .getFirst(paramName);
+    }
+
 
     private String getAppAccessToken(Long app_id, String app_secret){
         String url = "https://open.oceanengine.com/open_api/oauth2/app_access_token/";

+ 253 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/FeishuDocSyncServiceImpl.java

@@ -0,0 +1,253 @@
+package cn.com.ctop.job.bytedance.data.service.impl;
+
+import cn.com.ctop.job.bytedance.data.entity.AigcProductAlbum;
+import cn.com.ctop.job.bytedance.data.entity.AigcProductPlatform;
+import cn.com.ctop.job.bytedance.data.mapper.BytedanceProductUpdateMapper;
+import cn.com.ctop.job.bytedance.data.service.IFeishuDocSyncService;
+import cn.com.ctop.job.bytedance.data.utils.HttpUtils;
+import cn.com.ctop.job.bytedance.utils.BytedanceProductDocProperties;
+import cn.com.ctop.job.bytedance.utils.FeishuRobotUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+@Slf4j
+public class FeishuDocSyncServiceImpl implements IFeishuDocSyncService {
+    @Resource
+    BytedanceProductUpdateMapper bytedanceProductUpdateMapper;
+
+    @Autowired
+    BytedanceProductDocProperties productDocProperties;
+    @Override
+    public void syncBytedanceIaaProductPlatform() {
+        String readToken;
+        try {
+            readToken = getReadToken();
+        }catch (Exception e){
+            log.error("获取飞书文档读权限token失败",e);
+            return;
+        }
+
+
+    }
+
+    @Override
+    public void syncBytedanceIapProductPlatform() {
+        String readToken;
+        try {
+            readToken = getReadToken();
+        }catch (Exception e){
+            log.error("获取飞书文档读权限token失败",e);
+            return;
+        }
+    }
+
+    @Override
+    public void syncBytedanceDysDistributeMovies() {
+        if (productDocProperties.getDysMovies()==null|| productDocProperties.getDysMovies().isEmpty()){
+            return;
+        }
+
+        String readToken;
+        try {
+            readToken = getReadToken();
+        }catch (Exception e){
+            log.error("获取飞书文档读权限token失败",e);
+            return;
+        }
+        for (BytedanceProductDocProperties.DysDistributorLinkTable table : productDocProperties.getDysMovies()) {
+            System.out.println(table.getTableId()+table.getName());
+            List<AigcProductAlbum> iaaMmovies = readMovieFromDoc(productDocProperties.getObjToken(), table.getTableId(), table.getIaaViewId(), readToken, null);
+
+            if (iaaMmovies != null && !iaaMmovies.isEmpty()){
+                iaaMmovies.forEach(m -> {
+                    m.setSource(Integer.valueOf(table.getMovieSource()));
+                    m.setBusinessMethod("IAA");
+                    m.setPlayletId(getQueryParam(m.getAlbumLink(), "playlet_id"));
+                    m.setPlayletPurchasePanelId(getQueryParam(m.getAlbumLink(), "playlet_purchase_panel_id"));
+                });
+                bytedanceProductUpdateMapper.batchInsertDysDistributePlayletInfo(iaaMmovies);
+            }
+
+
+            if (StringUtils.isNotEmpty(table.getIapViewId())){
+                //iap
+                List<AigcProductAlbum> iapMovies = readMovieFromDoc(productDocProperties.getObjToken(), table.getTableId(), table.getIapViewId(), readToken, null);
+                if (iapMovies != null && !iapMovies.isEmpty()){
+                    iapMovies.forEach(m -> {
+                        m.setSource(Integer.valueOf(table.getMovieSource()));
+                        m.setBusinessMethod("IAP");
+                        m.setPlayletId(getQueryParam(m.getAlbumLink(), "playlet_id"));
+                        m.setPlayletPurchasePanelId(getQueryParam(m.getAlbumLink(), "playlet_purchase_panel_id"));
+                    });
+                    bytedanceProductUpdateMapper.batchInsertDysDistributePlayletInfo(iapMovies);
+                }
+            }
+        }
+    }
+
+    private List<AigcProductAlbum> readMovieFromDoc(String appToken,
+                                                    String tableId,
+                                                    String viewId,
+                                                    String accessToken,
+                                                    String pageToken){
+        String url = "https://open.feishu.cn/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/search";
+        url = url.replace(":app_token",appToken).replace(":table_id",tableId);
+        Map<String, Object> param = new HashMap<>();
+        if (StringUtils.isNotEmpty(viewId)){
+            param.put("view_id",viewId);
+        }
+        if (StringUtils.isNotEmpty(pageToken)){
+            url = url+"?page_token="+pageToken;
+        }
+        Map<String, String> headers = new HashMap<>();
+        headers.put("Authorization", "Bearer "+accessToken);
+        String res = HttpUtils.httpPostRequest(url, param, headers);
+        JSONObject resJson = JSONObject.parseObject(res);
+        if (resJson.getInteger("code")!=0){
+            log.error("调用飞书文档接口失败,res={}",res);
+            return null;
+        }
+        JSONObject data = resJson.getJSONObject("data");
+        JSONArray items = data.getJSONArray("items");
+        if (items==null||items.isEmpty()){
+            return null;
+        }
+
+        List<AigcProductAlbum> movies = new ArrayList<>();
+        for (int i = 0; i < items.size(); i++) {
+            JSONObject record = items.getJSONObject(i);
+            JSONObject fields = record.getJSONObject("fields");
+            AigcProductAlbum album = new AigcProductAlbum();
+            album.setName(getDocText(fields, "剧名"));
+            album.setAlbumLink(getDocText(fields, "推广链"));
+            if (StringUtils.isEmpty(album.getName()) || StringUtils.isEmpty(album.getAlbumLink())){
+                log.error("飞书文档剧目行数据不完整,record={}", fields.toJSONString());
+                continue;
+            }
+            movies.add(album);
+        }
+        boolean hasMore = data.getBooleanValue("has_more");
+        if (hasMore){
+            String nextPageToken = data.getString("page_token");
+            List<AigcProductAlbum> nextMovies = readMovieFromDoc(appToken, tableId, viewId, accessToken, nextPageToken);
+            if (nextMovies!=null&&!nextMovies.isEmpty()){
+                movies.addAll(nextMovies);
+            }
+        }
+        return movies;
+
+    }
+
+    /**
+     * 从飞书文档中读取商品库平台数据
+     * @param appToken 飞书表格appToken
+     * @param tableId 飞书表格ID
+     * @param viewId 飞书表格视图ID,可能没有
+     * @param accessToken 飞书机器人accessToken
+     * @param pageToken 第一次调用填null
+     * @return
+     */
+    private List<AigcProductPlatform> readPlatformFromDoc(String appToken, String tableId, String viewId, String accessToken, String pageToken){
+        String url = "https://open.feishu.cn/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/search";
+        url = url.replace(":app_token",appToken).replace(":table_id",tableId);
+        Map<String, Object> param = new HashMap<>();
+        if (StringUtils.isNotEmpty(viewId)){
+            param.put("view_id",viewId);
+        }
+        if (StringUtils.isNotEmpty(pageToken)){
+            url = url+"?page_token="+pageToken;
+        }
+        Map<String, String> headers = new HashMap<>();
+        headers.put("Authorization", "Bearer "+accessToken);
+        String res = HttpUtils.httpPostRequest(url, param, headers);
+        JSONObject resJson = JSONObject.parseObject(res);
+        if (resJson.getInteger("code")!=0){
+            log.error("调用飞书文档接口失败,res={}",res);
+            return null;
+        }
+        JSONObject data = resJson.getJSONObject("data");
+        JSONArray items = data.getJSONArray("items");
+        if (items==null||items.isEmpty()){
+            return null;
+        }
+        List<AigcProductPlatform> platforms = new ArrayList<>();
+        for (int i = 0; i < items.size(); i++) {
+            JSONObject item = items.getJSONObject(i);
+            JSONObject fields = item.getJSONObject("fields");
+            AigcProductPlatform platform = new AigcProductPlatform();
+            platform.setPlatformId(getDocText(fields, "商品库ID"));
+            platform.setAdvertiserId(getDocText(fields, "授权的广告主账户"));
+            platform.setType(1);
+            platform.setPlatformType(3);
+            platform.setPlatformName("欢瑞免费");
+            //todo
+
+            platforms.add(platform);
+        }
+
+
+        boolean hasMore = data.getBooleanValue("has_more");
+        if (hasMore){
+            String nextPageToken = data.getString("page_token");
+            List<AigcProductPlatform> nextPlatforms = readPlatformFromDoc(appToken, tableId, viewId, accessToken, nextPageToken);
+            if (nextPlatforms!=null&&!nextPlatforms.isEmpty()){
+                platforms.addAll(nextPlatforms);
+            }
+        }
+
+        return platforms;
+    }
+
+    private String getDocText(JSONObject fields, String columnName){
+        JSONArray jsonArray = fields.getJSONArray(columnName);
+        if (jsonArray==null||jsonArray.isEmpty()){
+            return null;
+        }
+        JSONObject field = jsonArray.getJSONObject(0);
+        return field.getString("text");
+    }
+
+    private String getDocFx(JSONObject fields, String columnName){
+        JSONObject field = fields.getJSONObject(columnName);
+        JSONArray value = field.getJSONArray("value");
+        if (value==null||value.isEmpty()){
+            return null;
+        }
+        JSONObject fieldValue = value.getJSONObject(0);
+        return fieldValue.getString("text");
+    }
+
+    private List<String> getDocSelects(JSONObject fields, String columnName){
+        JSONArray jsonArray = fields.getJSONArray(columnName);
+        if (jsonArray==null||jsonArray.isEmpty()){
+            return null;
+        }
+        return jsonArray.toJavaList(String.class);
+
+    }
+
+    private static String getQueryParam(String url, String paramName){
+        return UriComponentsBuilder.fromUriString(url)
+                .build()
+                .getQueryParams()
+                .getFirst(paramName);
+    }
+
+    private String getReadToken() throws IOException {
+        return FeishuRobotUtil.getTenantToken(FeishuRobotUtil.getFsDocreadAuth());
+    }
+}

+ 8 - 13
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/ReportsAdPushServiceImpl.java

@@ -32,7 +32,7 @@ public class ReportsAdPushServiceImpl implements IReportsAdPushService {
     public static final String APP_KEY = "OUlg7WTa6UWZItfTmJw2JdQvhVI4VcRj";
 
     public static final String TEMPLATE_ID = "AAqBGlVblKabY";
-    public static final String TEMPLATE_VERSION = "1.0.23";
+    public static final String TEMPLATE_VERSION = "1.0.24";
     @Autowired
     ReportsAdPushMapper reportsPushMapper;
 
@@ -139,7 +139,8 @@ public class ReportsAdPushServiceImpl implements IReportsAdPushService {
 //            obj.put("endAmount", m.get("water_end_amount"));
 //            obj.put("movieRealRoi", m.get("real_roi"));
             Double hourCostAmount = m.getDoubleValue("hour_cost_amount");
-            if (hourCostAmount >= 40000){
+            Double dayCostAmount = m.getDoubleValue("cost_amount");
+            if (hourCostAmount >= 30000 || dayCostAmount >=60000){
                 obj.put("movieName", "<font color='red'>"+m.getString("movie_name")+"(起量)</font>");
                 obj.put("hourCostAmount", "<font color='red'>"+hourCostAmount+"</font>");
             }else {
@@ -153,17 +154,11 @@ public class ReportsAdPushServiceImpl implements IReportsAdPushService {
             String iapAmount = String.valueOf(m.get("share_pay_amount"));
             obj.put("iaaRoi", iaaRoi+"\n"+iaaAmount);
             obj.put("iapRoi", iapRoi+"\n"+iapAmount);
-            String movieProjectSource = String.valueOf(m.get("movie_project_source"));
-            String movieProjectSourceName = String.valueOf(m.get("movie_project_source_name"));
-            JSONArray ms = new JSONArray();
-            if (!Check.isNull(movieProjectSource) && movieProjectSource.equals("1")){
-                ms.add(ImmutableMap.of("text", movieProjectSourceName, "color", "grey"));
-            }else if (!Check.isNull(movieProjectSource) && movieProjectSource.equals("2")){
-                ms.add(ImmutableMap.of("text", movieProjectSourceName, "color", "green"));
-            }else {
-                ms.add(ImmutableMap.of("text", movieProjectSourceName, "color", "blue"));
-            }
-            obj.put("movieProjectSource", ms);
+            String movieProjectSource = String.valueOf(m.get("movie_project_source_name"));
+            String projectAdStep = m.getString("project_ad_step");
+            String sb = "<text_tag color='blue'>" + movieProjectSource + "</text_tag>" +
+                    "<text_tag color='green'>" + projectAdStep + "</text_tag>";
+            obj.put("movieProjectSource", sb);
             object_list_2.add(obj);
         }
         template_variables.put("table_raw_array_1", object_list_2);

+ 6 - 5
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/ReportsByBusinessPushServiceImpl.java

@@ -103,11 +103,12 @@ public class ReportsByBusinessPushServiceImpl implements IReportsByBusinessPushS
 
         String updateTime = String.valueOf(todayData.get("update_time"));
         List<Pair<String, String>> columns = Arrays.asList(
-                new Pair<>("cost_amount", "消耗金额"),
-                new Pair<>("real_cost_amount", "折后消耗"),
-                new Pair<>("end_amount", "结算金额"),
-                new Pair<>("pay_amount", "充值金额"),
-                new Pair<>("iaa_amount", "广告预估收入"),
+//                new Pair<>("cost_amount", "消耗金额"),
+//                new Pair<>("real_cost_amount", "折后消耗"),
+                new Pair<>("water_end_amount", "流水总收入"),
+                new Pair<>("end_amount", "结算总收入"),
+//                new Pair<>("pay_amount", "充值金额"),
+//                new Pair<>("iaa_amount", "广告预估收入"),
 //                new Pair<>("water_roi", "流水ROI"),
 //                new Pair<>("real_roi", "真实ROI"),
 //                new Pair<>("water_profit", "流水利润"),

+ 10 - 1
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/handler/BytedanceProductUploadJob.java

@@ -1,6 +1,7 @@
 package cn.com.ctop.job.bytedance.handler;
 
 import cn.com.ctop.job.bytedance.data.service.IBytedanceProductUpdateService;
+import cn.com.ctop.job.bytedance.data.service.IFeishuDocSyncService;
 import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -11,6 +12,8 @@ import org.springframework.stereotype.Component;
 public class BytedanceProductUploadJob {
     @Autowired
     IBytedanceProductUpdateService bytedanceProductUpdateService;
+    @Autowired
+    IFeishuDocSyncService feishuDocSyncService;
 
     /**
      * 创建和更新推广链
@@ -18,7 +21,13 @@ public class BytedanceProductUploadJob {
      */
     @XxlJob("productUploadJob")
     public void productUploadJob() throws Exception {
-        bytedanceProductUpdateService.run();
+        bytedanceProductUpdateService.runMp();
+    }
+
+    @XxlJob("dysDistributeProductUploadJob")
+    public void dysDistributeProductUploadJob() throws Exception{
+        feishuDocSyncService.syncBytedanceDysDistributeMovies();
+        bytedanceProductUpdateService.runDysDistribute();
     }
 
     /**

+ 16 - 4
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/handler/BytedanceReportRetryJob.java

@@ -3,6 +3,7 @@ package cn.com.ctop.job.bytedance.handler;
 
 import cn.com.ctop.job.bytedance.config.DianZhongConfig;
 import cn.com.ctop.job.bytedance.data.enums.AccountTypeEnum;
+import cn.com.ctop.job.bytedance.data.mapper.BytedancePromoterReportMapper;
 import cn.com.ctop.job.bytedance.data.service.*;
 import cn.com.ctop.job.bytedance.data.utils.Check;
 import com.alibaba.fastjson.JSONObject;
@@ -59,6 +60,9 @@ public class BytedanceReportRetryJob {
     @Resource
     private DianZhongConfig dianZhongConfig;
 
+    @Autowired
+    private BytedancePromoterReportMapper promoterReportMapper;
+
 
     private static ExecutorService hourAccountRetrExecutorService = Executors.newFixedThreadPool(2);
     private static ExecutorService dailyAccountRetrExecutorService = Executors.newFixedThreadPool(2);
@@ -67,6 +71,7 @@ public class BytedanceReportRetryJob {
     private static ExecutorService hourPromoterRetrExecutorService = Executors.newFixedThreadPool(2);
 
     private static ExecutorService productDailyRetrExecutor = Executors.newFixedThreadPool(2);
+    private static ExecutorService materialRetrExecutor = Executors.newFixedThreadPool(3);
 
     private static ExecutorService flowDailyRetrExecutor = Executors.newFixedThreadPool(2);
     private static ExecutorService changduExecutorService = Executors.newFixedThreadPool(1);
@@ -88,6 +93,7 @@ public class BytedanceReportRetryJob {
                 Integer isSend = jsonObject.getInteger("isSend");
                 String msg = jsonObject.getString("msg");
                 if ("promoter".equals(dataDimension)) {
+                    promoterReportMapper.updateStatusByErrorId(id);
                     if (dataType.equals("hour")) { // 广告时报
                         hourPromoterRetrExecutorService.submit(new Runnable() {
                             @Override
@@ -110,6 +116,7 @@ public class BytedanceReportRetryJob {
                         });
                     }
                 } else if ("product".equals(dataDimension)) {
+                    promoterReportMapper.updateStatusByErrorId(id);
                     productDailyRetrExecutor.submit(new Runnable() {
                         @Override
                         public void run() {
@@ -119,6 +126,7 @@ public class BytedanceReportRetryJob {
                         }
                     });
                 } else if ("account".equals(dataDimension)) {
+                    promoterReportMapper.updateStatusByErrorId(id);
                     if (dataType.equals("hour")) { // 账户时报
                         hourAccountRetrExecutorService.submit(new Runnable() {
                             @Override
@@ -142,15 +150,16 @@ public class BytedanceReportRetryJob {
                     }
 
                 } else if ("flow_details".equals(dataDimension)) { //日报流水详情
+                    promoterReportMapper.updateStatusByErrorId(id);
                     flowDailyRetrExecutor.submit(new Runnable() {
-
                         @Override
                         public void run() {
                             byteDanceFlowDetailsReportService.getBytedanceFlowDetailsDailyReport(advertiserId, accessToken, AccountTypeEnum.AD.getValue(), startDate, endDate, 1, id);
                         }
                     });
                 } else if ("material".equals(dataDimension)) {
-                    productDailyRetrExecutor.submit(new Runnable() {
+                    promoterReportMapper.updateStatusByErrorId(id);
+                    materialRetrExecutor.submit(new Runnable() {
                         @Override
                         public void run() {
                             if (!Check.isNull(accessToken)) {
@@ -159,12 +168,13 @@ public class BytedanceReportRetryJob {
                         }
                     });
                 } else if ("material_video_get".equals(dataDimension)) {
+                    promoterReportMapper.updateStatusByErrorId(id);
                     HashSet<Long> materialIds = new HashSet<>();
                     JSONObject msgObject = JSONObject.parseObject(msg);
                     if (msgObject != null && msgObject.getJSONArray("material_ids") != null) {
                         materialIds.addAll(msgObject.getJSONArray("material_ids").toJavaList(Long.class));
                     }
-                    productDailyRetrExecutor.submit(new Runnable() {
+                    materialRetrExecutor.submit(new Runnable() {
                         @Override
                         public void run() {
                             if (!Check.isNull(accessToken)) {
@@ -173,6 +183,7 @@ public class BytedanceReportRetryJob {
                         }
                     });
                 } else if ("promotion_list".equals(dataDimension)) {
+                    promoterReportMapper.updateStatusByErrorId(id);
                     productDailyRetrExecutor.submit(new Runnable() {
                         @Override
                         public void run() {
@@ -182,6 +193,7 @@ public class BytedanceReportRetryJob {
                         }
                     });
                 } else if ("project_list".equals(dataDimension)) {
+                    promoterReportMapper.updateStatusByErrorId(id);
                     productDailyRetrExecutor.submit(new Runnable() {
                         @Override
                         public void run() {
@@ -242,7 +254,7 @@ public class BytedanceReportRetryJob {
                     changduExecutorService.submit(new Runnable() {
                         @Override
                         public void run() {
-                            miniAppService.getMaEcpm(startDate, endDate, appId, 1, id, isSend);
+                            miniAppService.getMaEcpm(startDate, endDate, appId, 0, id, isSend);
                         }
                     });
                 }

+ 4 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/handler/ToolsSiteJob.java

@@ -109,6 +109,10 @@ public class ToolsSiteJob {
         //更新短剧上下架状态
         String url = "https://api.cms.artlinkworld.cn/videoAppletShow/regularUpdatesState";
         HttpUtils.httpGet(String.format("%s?id=%s", url, KEY), null, null);
+
+        //授权IAA微信小程序,(当配置完iaa上架时间后,根据上架时间,提前30分钟进行授权)
+        String url2 = "https://api.cms.artlinkworld.cn/videoAppletShow/authorizedIaaWechatApp";
+        HttpUtils.httpGet(String.format("%s?id=%s", url2, KEY), null, null);
     }
 
     @XxlJob("regularUpdateVideoInfo")

+ 39 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/utils/BytedanceProductDocProperties.java

@@ -0,0 +1,39 @@
+package cn.com.ctop.job.bytedance.utils;
+
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Lazy
+@Setter
+@Getter
+@Component
+@ConfigurationProperties(prefix = "feishu.doc.bytedance-platform")
+public class BytedanceProductDocProperties {
+
+    private String objToken;
+    private ProductPlatformTable iaa;
+    private ProductPlatformTable iap;
+    private List<DysDistributorLinkTable> dysMovies;
+
+    @Data
+    public static class ProductPlatformTable{
+        private String tableId;
+        private String viewId;
+    }
+
+    @Data
+    public static class DysDistributorLinkTable {
+        private String name;
+        private String tableId;
+        private String iaaViewId;
+        private String iapViewId;
+        private String movieSource;
+        private String copyrightOwner;
+    }
+}

+ 5 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/utils/FeishuRobotUtil.java

@@ -29,6 +29,8 @@ public class FeishuRobotUtil {
     public static final String fs_adlb2_appkey = "NRclULz12k35lkAktx9FigX7oGh2kCw1";
     public static final String fs_adlb3_appid = "cli_a76e77711cce900e";//广告账号漏绑预警应用
     public static final String fs_adlb3_appkey = "eG6gExoSotb4gRlkB4PuvccgGdfBNTTS";
+    public static final String fs_docread_appid = "cli_a99e83cac117500b";
+    public static final String fs_docread_appkey = "xStPMP3IQSLbYxW3kpfo0epIwr0pSNrB";
 
     //"{\"app_id\":\"cli_a75d0ab0f538100e\",\"app_secret\":\"w7ZNwahiXkmh1xCVSjt8ccJsaleIL3Fc\"}"
     public static String getFsZtAuth() {
@@ -43,6 +45,9 @@ public class FeishuRobotUtil {
     public static String getFsAdlb3Auth() {
         return "{\"app_id\":\"" + fs_adlb3_appid + "\",\"app_secret\":\"" + fs_adlb3_appkey + "\"}";
     }
+    public  static String getFsDocreadAuth() {
+        return "{\"app_id\":\"" + fs_docread_appid + "\",\"app_secret\":\"" + fs_docread_appkey + "\"}";
+    }
 
     public static String getFsZtTenantToken() throws IOException {
         return getTenantToken(getFsZtAuth());

+ 45 - 1
job-bytedance/src/main/resources/application.yml

@@ -84,7 +84,7 @@ spring:
       datasource:
         master:
           url: jdbc:mysql://172.16.0.117:3390/media_api?characterEncoding=UTF-8&useUnicode=true&useSSL=false
-          #url: jdbc:mysql://8.147.135.80:3390/media_api?characterEncoding=UTF-8&useUnicode=true&allowMultiQueries=true&useSSL=false
+#          url: jdbc:mysql://8.147.135.80:3390/media_api?characterEncoding=UTF-8&useUnicode=true&allowMultiQueries=true&useSSL=false
           username: yanfa
           password: hr@2025..
           driver-class-name: com.mysql.jdbc.Driver
@@ -190,3 +190,47 @@ playlet:
     bucketName: short-theatre-hr
     csjDomain: https://oss.artlinkworld.cn/
     csjFileDir: csj/
+
+# 飞书拉取的表格配置
+feishu:
+  doc:
+    bytedance-platform:
+      objToken: AfLHbNJ9uamORqsvxq8cy63jnPc
+      iaa:
+        tableId: tblsf6RT9HAamt8k
+      iap:
+        tableId: tbl5BPc8DHLIu4Ac
+      dysMovies[0]:
+        name: 番茄端原生推广链
+        tableId: tblPAu0mOPStWGfQ
+        iaaViewId: vewnjgPWGB
+        movieSource: 24
+        copyrightOwner: 抖音视界有限公司
+      dysMovies[1]:
+        name: 日新端原生推广链
+        tableId: tblstFPWYbx172ey
+        iaaViewId: vewnjgPWGB
+        iapViewId: vewbYuvx4z
+        movieSource: 18
+        copyrightOwner: 日新端
+      dysMovies[2]:
+        name: 胜事端原生推广链
+        tableId: tbl0IWs5PsvW3Q4q
+        iaaViewId: vewnjgPWGB
+        iapViewId: vewbYuvx4z
+        movieSource: 10
+        copyrightOwner: 胜事端
+      dysMovies[3]:
+        name: 友和端原生推广链
+        tableId: tblJWHRxZLtVEH6n
+        iaaViewId: vewnjgPWGB
+        iapViewId: vewbYuvx4z
+        movieSource: 22
+        copyrightOwner: 友和端
+      dysMovies[4]:
+        name: 百川端原生推广链
+        tableId: tblqN0gRgLBipgCd
+        iaaViewId: vewnjgPWGB
+        iapViewId: vewbYuvx4z
+        movieSource: 19
+        copyrightOwner: 百川端