Index: jinan/trunk/yunna/src/main/java/com/freshport/common/DruidDataSourceConfiguration.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/common/DruidDataSourceConfiguration.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/common/DruidDataSourceConfiguration.java	(revision 33814)
@@ -1,5 +1,8 @@
 package com.freshport.common;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.sql.DataSource;
 
 import org.apache.ibatis.session.SqlSessionFactory;
@@ -11,14 +14,25 @@
 import org.springframework.context.annotation.Primary;
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 
+import com.alibaba.druid.filter.Filter;
+import com.alibaba.druid.filter.stat.StatFilter;
 import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.wall.WallConfig;
+import com.alibaba.druid.wall.WallFilter;
 
 @Configuration
 public class DruidDataSourceConfiguration {
     @Bean("druidDataSource")
     @ConfigurationProperties(prefix = "spring.datasource")
     public DataSource druidDataSource() {
-        DataSource druidDataSource = new DruidDataSource();
+        // DataSource druidDataSource = new DruidDataSource();
+        DruidDataSource druidDataSource = new DruidDataSource();
+
+        List<Filter> filterList = new ArrayList<>();
+        filterList.add(wallFilter());
+        filterList.add(statFilter());
+        druidDataSource.setProxyFilters(filterList);
+
         return druidDataSource;
     }
 
@@ -36,4 +50,26 @@
 
         return sessionFactoryBean.getObject();
     }
+
+    @Bean
+    public StatFilter statFilter() {
+        StatFilter statFilter = new StatFilter();
+        return statFilter;
+    }
+
+    @Bean
+    public WallFilter wallFilter() {
+        WallFilter wallFilter = new WallFilter();
+        wallFilter.setConfig(wallConfig());
+        return wallFilter;
+    }
+
+    @Bean
+    public WallConfig wallConfig() {
+        WallConfig config = new WallConfig();
+        config.setMultiStatementAllow(true);// 允许一次执行多条语句
+        config.setNoneBaseStatementAllow(true);// 允许非基本语句的其他语句
+        return config;
+    }
+
 }
Index: jinan/trunk/yunna/src/main/java/com/freshport/config/ThreadPoolConfig.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/config/ThreadPoolConfig.java	(revision 0)
+++ jinan/trunk/yunna/src/main/java/com/freshport/config/ThreadPoolConfig.java	(revision 33814)
@@ -0,0 +1,37 @@
+package com.freshport.config;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 线程池配置（复制其他项目）
+ *     
+ * 项目名称：yunna    
+ * 类名称：ThreadPoolConfig    
+ * 类描述：    
+ * 创建人：lixd    
+ * 创建时间：2023年3月28日 下午3:34:37    
+ * 修改人：lixd    
+ * 修改时间：2023年3月28日 下午3:34:37    
+ * 修改备注：    
+ * @version     
+ *
+ */
+@Configuration
+public class ThreadPoolConfig {
+    /**
+     * 获取线程池
+     *
+     * @return
+     */
+    @Bean
+    public ThreadPoolExecutor getThreadPoolExecutor() {
+        // 5个核心线程，最大10个线程， 每个线程最大1000个任务
+        return new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000),
+                new ThreadPoolExecutor.DiscardPolicy());
+    }
+}


Index: jinan/trunk/yunna/src/main/java/com/freshport/control/FruitShipPortControl.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/control/FruitShipPortControl.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/control/FruitShipPortControl.java	(revision 33814)
@@ -8,6 +8,7 @@
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import com.alibaba.fastjson.JSONObject;
@@ -59,15 +60,16 @@
     public JsonModel<List<LoadingNumberResultVO>> getLoadingNumberInfo(@RequestBody LoadingNumberQueryParam params) {
 
         JsonModel<List<LoadingNumberResultVO>> model = new JsonModel<List<LoadingNumberResultVO>>();
-        log.debug("========获取提单号接口参数：{}", JSONObject.toJSONString(params));
+        log.info("========获取提单号接口参数：{}", JSONObject.toJSONString(params));
 
         if (CommonUtils.isEmpty(params) || CommonUtils.isEmpty(params.getType())) {
 
             model.setCode(CommonEnum.PARAM_ERROR.getCode());
             model.setDes(CommonEnum.PARAM_ERROR.getRes());
             fruitShipPortService.saveShipPortLog(JSONObject.toJSON(params).toString(),
-                    JSONObject.toJSON(model).toString(), params.getType(), "提单号查询-结果条数：0", "");
+                    JSONObject.toJSON(model).toString(), CommonInfo.LOG_TYPE_LOADING_SHIP, 0, "");
 
+            log.info("========获取提单号接口返回结果：{}", JSONObject.toJSONString(model));
             return model;
         }
         if (!CommonInfo.TYPE_SHIP.equals(params.getType()) && !CommonInfo.TYPE_PORT.equals(params.getType())
@@ -77,14 +79,23 @@
             model.setCode(CommonEnum.PARAM_ERROR.getCode());
             model.setDes(CommonEnum.PARAM_ERROR.getRes());
             fruitShipPortService.saveShipPortLog(JSONObject.toJSON(params).toString(),
-                    JSONObject.toJSON(model).toString(), params.getType(), "提单号查询-结果条数：0", "");
+                    JSONObject.toJSON(model).toString(), params.getType(), 0, "");
 
+            log.info("========获取提单号接口返回结果：{}", JSONObject.toJSONString(model));
             return model;
         }
 
         List<LoadingNumberResultVO> resultList = new ArrayList<LoadingNumberResultVO>();
         try {
-            resultList = fruitShipPortService.queryLoadingNumberInfoList(params);
+
+            try {
+                resultList = fruitShipPortService.queryLoadingNumberInfoList(params);
+            } catch (Exception e) {
+                e.printStackTrace();
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PROGRAM, "",
+                        "查询提单号接口-程序异常：" + e.getMessage());
+            }
+
             model = JsonModel.success(resultList);
         } catch (BaseException e) {
             e.printStackTrace();
@@ -94,6 +105,13 @@
             e.printStackTrace();
             log.error("getLoadingNumberInfo_error", e.getMessage());
             model = JsonModel.error(CommonEnum.API_ERROR.getRes());
+
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PROGRAM, "",
+                        "查询提单号接口-程序异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
         String batchNo = "";
         if (!CommonUtils.isEmpty(resultList) && resultList.size() > 0) {
@@ -102,8 +120,9 @@
             batchNo = resultList.get(0).getBatchNo();
         }
         fruitShipPortService.saveShipPortLog(JSONObject.toJSON(params).toString(), JSONObject.toJSON(model).toString(),
-                params.getType(), "提单号查询-结果条数：" + resultList.size(), batchNo);
+                params.getType(), resultList.size(), batchNo);
 
+        log.info("========获取提单号接口返回结果：{}", JSONObject.toJSONString(model));
         return model;
     }
 
@@ -121,19 +140,28 @@
     public JsonModel<Object> saveShipInfo(@RequestBody List<ShipPortResultVO> params) {
 
         JsonModel<Object> model = new JsonModel<Object>();
-        log.debug("========回传船司参数：{}", JSONObject.toJSONString(params));
+        log.info("========回传船司参数：{}", JSONObject.toJSONString(params));
 
         if (CommonUtils.isEmpty(params)) {
             model.setCode(CommonEnum.PARAM_ERROR.getCode());
             model.setDes(CommonEnum.PARAM_ERROR.getRes());
             fruitShipPortService.saveShipPortLog(JSONObject.toJSON(params).toString(),
-                    JSONObject.toJSON(model).toString(), CommonInfo.TYPE_SHIP, "回传船司结果-条数：" + params.size(), "");
+                    JSONObject.toJSON(model).toString(), CommonInfo.LOG_TYPE_RESULT_SHIP, params.size(), "");
 
+            log.info("========回传船司返回结果：{}", JSONObject.toJSONString(model));
             return model;
         }
 
         try {
-            fruitShipPortService.saveShipInfo(params);
+
+            try {
+                fruitShipPortService.saveShipInfo(params);
+            } catch (Exception e) {
+                e.printStackTrace();
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PROGRAM, "",
+                        "回传船司信息接口-程序异常：" + e.getMessage());
+            }
+
             model = JsonModel.success(CommonEnum.API_SUCCESS.getRes());
         } catch (BaseException e) {
             e.printStackTrace();
@@ -143,6 +171,13 @@
             e.printStackTrace();
             log.error("saveShipInfo_error", e.getMessage());
             model = JsonModel.error(CommonEnum.API_ERROR.getRes());
+
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PROGRAM, "",
+                        "回传船司信息接口-程序异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
 
         String batchNo = "";
@@ -152,8 +187,9 @@
             batchNo = params.get(0).getBatchNo();
         }
         fruitShipPortService.saveShipPortLog(JSONObject.toJSON(params).toString(), JSONObject.toJSON(model).toString(),
-                CommonInfo.TYPE_SHIP, "回传船司结果-条数：" + params.size(), batchNo);
+                CommonInfo.LOG_TYPE_RESULT_SHIP, params.size(), batchNo);
 
+        log.info("========回传船司返回结果：{}", JSONObject.toJSONString(model));
         return model;
     }
 
@@ -171,19 +207,29 @@
     public JsonModel<Object> savePortInfo(@RequestBody List<ShipPortResultVO> params) {
 
         JsonModel<Object> model = new JsonModel<Object>();
-        log.debug("========回传港口参数：{}", JSONObject.toJSONString(params));
+        log.info("========回传港口参数：{}", JSONObject.toJSONString(params));
 
         if (CommonUtils.isEmpty(params)) {
             model.setCode(CommonEnum.PARAM_ERROR.getCode());
             model.setDes(CommonEnum.PARAM_ERROR.getRes());
 
             fruitShipPortService.saveShipPortLog(JSONObject.toJSON(params).toString(),
-                    JSONObject.toJSON(model).toString(), CommonInfo.TYPE_PORT, "回传港口结果-条数：" + params.size(), "");
+                    JSONObject.toJSON(model).toString(), CommonInfo.LOG_TYPE_RESULT_PORT, params.size(), "");
+
+            log.info("========回传港口返回结果：{}", JSONObject.toJSONString(model));
             return model;
         }
         try {
-            fruitShipPortService.savePortInfo(params);
-            model = JsonModel.success("成功");
+
+            try {
+                fruitShipPortService.savePortInfo(params);
+            } catch (Exception e) {
+                e.printStackTrace();
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PROGRAM, "",
+                        "回传港口信息接口-程序异常：" + e.getMessage());
+            }
+
+            model = JsonModel.success(CommonEnum.API_SUCCESS.getRes());
         } catch (BaseException e) {
             e.printStackTrace();
             log.error("savePortInfo_error", e.getMessage());
@@ -192,6 +238,13 @@
             e.printStackTrace();
             log.error("savePortInfo_error", e.getMessage());
             model = JsonModel.error(CommonEnum.API_ERROR.getRes());
+
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PROGRAM, "",
+                        "回传港口信息接口-程序异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
 
         String batchNo = "";
@@ -201,9 +254,54 @@
             batchNo = params.get(0).getBatchNo();
         }
         fruitShipPortService.saveShipPortLog(JSONObject.toJSON(params).toString(), JSONObject.toJSON(model).toString(),
-                CommonInfo.TYPE_PORT, "回传港口结果-条数：" + params.size(), batchNo);
+                CommonInfo.LOG_TYPE_RESULT_PORT, params.size(), batchNo);
 
+        log.info("========回传港口返回结果：{}", JSONObject.toJSONString(model));
         return model;
     }
 
+    /**
+     * 
+     * savePortOrShipInfo(手动调用，重新更新船司/港口信息)      
+     * @param type
+     * @param batchNo
+     * @return  
+     * @return JsonModel<Object>  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-28 15:36:52
+     */
+    @PostMapping("/savePortOrShipInfo")
+    public JsonModel<Object> savePortOrShipInfo(@RequestParam("type") String type,
+            @RequestParam("batchNo") String batchNo) {
+
+        JsonModel<Object> model = new JsonModel<Object>();
+        log.info("========手动更新船司/港口信息-参数：type:{}, batchNo:{}", type, batchNo);
+
+        if (CommonUtils.isEmpty(type) || CommonUtils.isEmpty(batchNo)) {
+            model.setCode(CommonEnum.PARAM_ERROR.getCode());
+            model.setDes(CommonEnum.PARAM_ERROR.getRes());
+
+            log.info("========手动更新船司/港口信息-返回结果：{}", JSONObject.toJSONString(model));
+            return model;
+        }
+        try {
+
+            fruitShipPortService.savePortOrShipInfo(type, batchNo);
+
+            model = JsonModel.success(CommonEnum.API_SUCCESS.getRes());
+        } catch (BaseException e) {
+            e.printStackTrace();
+            log.error("savePortOrShipInfo_error", e.getMessage());
+            model = JsonModel.error(e.getMessage());
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("savePortOrShipInfo_error", e.getMessage());
+            model = JsonModel.error(CommonEnum.API_ERROR.getRes());
+        }
+
+        log.info("========手动更新船司/港口信息-返回结果：{}", JSONObject.toJSONString(model));
+        return model;
+    }
+
 }
Index: jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/ShipPortMapper.xml
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/ShipPortMapper.xml	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/ShipPortMapper.xml	(revision 33814)
@@ -57,7 +57,7 @@
 			distinct
 			REPLACE(yh.ztdh, '*', '') as loadingNumber,
 			yh.ywbh as businessNo,
-			'' as containerNumber,
+			(SELECT isnull(max(jzxxx.jzxh), '') from yw_hddz_jzxxx jzxxx WHERE jzxxx.ywbh = yh.ywbh and isnull(jzxxx.jzxh, '') != '') as containerNumber,
 			yh.mdg as destinationPort,
 			yc.carrier_code as firmName,
 			'' as shipName,
@@ -133,7 +133,7 @@
 			distinct
 			REPLACE(yh.ztdh, '*', '') as loadingNumber,
 			yh.ywbh as businessNo,
-			'' as containerNumber,
+			(SELECT isnull(max(jzxxx.jzxh), '') from yw_hddz_jzxxx jzxxx WHERE jzxxx.ywbh = yh.ywbh and isnull(jzxxx.jzxh, '') != '') as containerNumber,
 			yh.mdg as destinationPort,
 			yc.carrier_code as firmName,
 			'' as shipName,
@@ -161,7 +161,8 @@
 		REPLACE( yh.ztdh, '*', '' ) AS loadingNumber,
 		yh.ywbh as businessNo,
 		jzxxx.jzxh AS containerNumber,
-		yh.mdg AS destinationPort,
+		<!-- yh.mdg AS destinationPort, -->
+		ysdp.destination_port_code as destinationPort,
 		CASE
 				WHEN yh.mdg = '上海' THEN
 				isnull( yh.cm, '' ) ELSE '' 
@@ -174,21 +175,23 @@
 	FROM
 		yw_hddz_jzxxx jzxxx
 		LEFT JOIN yw_hddz yh ON yh.ywbh = jzxxx.ywbh 
+		LEFT JOIN yw_ship_destination_port ysdp on ysdp.mdg = yh.mdg
 	WHERE
 		yh.ysfs = '海运' 
 		AND isnull( yh.state, '新制' ) = '新制' 
-		<!-- AND jzxxx.xcsj IS NULL  -->
+		AND jzxxx.xcsj IS NULL 
 		AND isnull( yh.jckfs, '' ) = '进口' 
 		AND isnull( yh.ztdh, '' ) != '' 
 		AND isnull( jzxxx.jzxh, '' ) != '' 
 		AND (
-			yh.mdg IN ( '宁波', '青岛', '天津', '上海', '厦门港', '盐田', '广州' ) 
-		OR ( yh.mdg = '南沙新港' AND yh.xhgqjc = '南沙三期' )) 
+			yh.mdg IN ( '宁波', '青岛', '天津', '上海', '盐田' ) 
+		OR ( yh.mdg = '南沙新港' AND isnull(yh.xhgqjc, '') = '南沙三期' )
+		OR (yh.mdg = '厦门港' and isnull(yh.xhgqjc, '') != '远海码头')) 
 		AND DATEDIFF( HOUR, getdate(), yh.yjkgsj ) BETWEEN 1 AND 72 
 		and yh.zbrq &lt;= getdate()
-		and exists (
+		<!-- and exists (
 			SELECT 1 from yw_hddz_jzxxx yhj WHERE yhj.ywbh = yh.ywbh and yhj.xcsj is null
-		)
+		) -->
   </select>
   
   <!-- 查询提单号信息 港口类型 -->
@@ -197,7 +200,8 @@
 		REPLACE( yh.ztdh, '*', '' ) AS loadingNumber,
 		yh.ywbh as businessNo,
 		jzxxx.jzxh AS containerNumber,
-		yh.mdg AS destinationPort,
+		<!-- yh.mdg AS destinationPort, -->
+		ysdp.destination_port_code as destinationPort,
 		CASE
 				WHEN yh.mdg = '上海' THEN
 				isnull( yh.cm, '' ) ELSE '' 
@@ -210,21 +214,23 @@
 	FROM
 		yw_hddz_jzxxx jzxxx
 		LEFT JOIN yw_hddz yh ON yh.ywbh = jzxxx.ywbh 
+		LEFT JOIN yw_ship_destination_port ysdp on ysdp.mdg = yh.mdg
 	WHERE
 		yh.ysfs = '海运' 
 		AND isnull( yh.state, '新制' ) = '新制' 
-		<!-- AND jzxxx.xcsj IS NULL  -->
+		AND jzxxx.xcsj IS NULL 
 		AND isnull( yh.jckfs, '' ) = '进口' 
 		AND isnull( yh.ztdh, '' ) != '' 
 		AND isnull( jzxxx.jzxh, '' ) != '' 
 		AND (
-			yh.mdg IN ( '宁波', '青岛', '天津', '上海', '厦门港', '盐田', '广州' ) 
-		OR ( yh.mdg = '南沙新港' AND yh.xhgqjc = '南沙三期' )) 
+			yh.mdg IN ( '宁波', '青岛', '天津', '上海', '盐田' ) 
+		OR ( yh.mdg = '南沙新港' AND isnull(yh.xhgqjc, '') = '南沙三期' )
+		OR (yh.mdg = '厦门港' and isnull(yh.xhgqjc, '') != '远海码头')) 
 		AND DATEDIFF( HOUR, getdate(), yh.yjkgsj ) BETWEEN 1 AND 72 
 		and yh.zbrq between CONVERT ( CHAR ( 10 ), getdate(), 126 ) + ' 00:00:00' and CONVERT ( CHAR ( 10 ), getdate(), 126 ) + ' 16:00:00'
-		and exists (
+		<!-- and exists (
 			SELECT 1 from yw_hddz_jzxxx yhj WHERE yhj.ywbh = yh.ywbh and yhj.xcsj is null
-		)
+		) -->
   </select>
   
   <select id="listPortInfoForHddz" parameterType="java.lang.String" resultType="com.freshport.entity.yunna.PortForHddzVO">
@@ -237,7 +243,7 @@
 		yspr.expect_arrival_time AS expectArrivalTime,
 		yspr.actual_port_time AS actualPortTime,
 		isnull(yspr.voyage, '') AS voyage,
-		isnull(yh.zz_hcorhbh, '') as zZHcorhbh, 
+		isnull(yh.zz_hcorhbh, '') as zzHcorhbh, 
 		isnull(yspr.unloading_port, '') AS unloadingPort,
 		isnull(ysu.unloading_port_short_name, '') as unloadingPortShortName,
 		isnull(ysu.unloading_port_full_name, '') as unloadingPortFullName,
@@ -252,13 +258,14 @@
 	WHERE
 		yspr.batch_no = #{batchNo}
 		AND yspr.type = 'PORT'
+		and yspr.status in ('0')
   </select>
   
   <update id="updatePortInfoListForHddz" parameterType="java.util.List">
   	<foreach collection="list" separator=";" item="item">
   	  		update yw_hddz
     		<set> 
-    			yjkgsj = #{item.expectArrivalTime},
+    			yjkgsj = #{item.newExpectArrivalTime},
     			sjkgsj = #{item.actualPortTime},
     			rpa_xrsj = getdate(),
     			<if test="item.unloadingPortCode != null and item.unloadingPortCode != ''">
@@ -267,7 +274,7 @@
 	    			xhgqbm = #{item.unloadingPortCode},
 		      	</if>
 		      	<choose>
-		            <when test="item.zZHcorhbh != null and item.zZHcorhbh != ''">
+		            <when test="item.zzHcorhbh != null and item.zzHcorhbh != ''">
 		                zz_hcorhbh = #{item.voyage},
 		            </when>
 		            <otherwise>
@@ -298,7 +305,8 @@
 		isnull(yspr.destination_port, '') as destinationPort,
 		isnull(yh.mdg, '') AS mdg,
 		yspr.expect_arrival_time AS expectArrivalTime,
-		DATEDIFF( HOUR, yspr.crt_time, yspr.expect_arrival_time ) hours,
+		yspr.crt_time as crtTime,
+		isnull(DATEDIFF( HOUR, yspr.crt_time, yspr.expect_arrival_time ), 0)  hours,
 		yspr.transit_port as transitPort,
 		isnull(yspr.ship_name, '') as shipName, 
 		isnull(yh.cm, '') as ladingShipName, 
@@ -310,8 +318,9 @@
 		yw_ship_port_result yspr
 		LEFT JOIN yw_hddz yh ON yspr.business_no = yh.ywbh 
 	WHERE
-		yspr.batch_no = '#{batchNo}'
+		yspr.batch_no = #{batchNo}
 		AND yspr.type = 'SHIP'
+		and yspr.status in ('0')
   </select>
   
   <update id="updateShipInfoListForHddz" parameterType="java.util.List">
@@ -323,13 +332,23 @@
     			zz_cm = #{item.transitShipName},
     			zz_hcorhbh = #{item.transitVoyage},
     			kcsj = #{item.actualSailingTime},
-    			rpa_xrsj = getdate(),
-    			<if test="item.hours != null and item.hours > 72">
+    			rpa_xrsj = getdate()
+    			<!-- <if test="item.hours != null and item.hours > 72">
 		        	yjkgsj = #{item.expectArrivalTime},
-		      	</if>
+		      	</if> -->
 		      </set>
 		    where ywbh = #{item.businessNo}
   	</foreach>
   </update>
   
+  <update id="updateShipEtaListForHddz" parameterType="java.util.List">
+  	<foreach collection="list" separator=";" item="item">
+  	  		update yw_hddz
+    		<set> 
+		        	yjkgsj = #{item.newExpectArrivalTime}
+		    </set>
+		    where ywbh = #{item.businessNo}
+  	</foreach>
+  </update>
+  
 </mapper>
\ No newline at end of file
Index: jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/YwShipPortLoadingMapper.xml
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/YwShipPortLoadingMapper.xml	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/YwShipPortLoadingMapper.xml	(revision 33814)
@@ -234,4 +234,8 @@
 	from yw_ship_port_loading 
 	where batch_no like #{dateStr}+ '%' 
   </select>
+  
+  <select id="countByBatchNo" parameterType="java.lang.String" resultType="java.lang.Integer">
+  	select count(1) from yw_ship_port_loading where batch_no = #{batchNo}
+  </select>
 </mapper>
\ No newline at end of file
Index: jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/YwShipPortLogMapper.xml
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/YwShipPortLogMapper.xml	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/YwShipPortLogMapper.xml	(revision 33814)
@@ -12,6 +12,7 @@
     <result column="upd_time" jdbcType="TIMESTAMP" property="updTime" />
     <result column="upd_host" jdbcType="VARCHAR" property="updHost" />
     <result column="batch_no" jdbcType="VARCHAR" property="batchNo" />
+    <result column="total_number" jdbcType="INTEGER" property="totalNumber" />
   </resultMap>
   <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.freshport.entity.YwShipPortLogWithBLOBs">
     <result column="msg" jdbcType="LONGVARCHAR" property="msg" />
@@ -19,7 +20,7 @@
   </resultMap>
   <sql id="Base_Column_List">
     yspl_id, type, remark, crt_user, crt_time, crt_host, upd_user, upd_time, upd_host, 
-    batch_no
+    batch_no, total_number
   </sql>
   <sql id="Blob_Column_List">
     msg, result
@@ -40,13 +41,13 @@
     insert into yw_ship_port_log (yspl_id, type, remark, 
       crt_user, crt_time, crt_host, 
       upd_user, upd_time, upd_host, 
-      batch_no, msg, result
-      )
+      batch_no, total_number, msg, 
+      result)
     values (#{ysplId,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR}, 
       #{crtUser,jdbcType=VARCHAR}, #{crtTime,jdbcType=TIMESTAMP}, #{crtHost,jdbcType=VARCHAR}, 
       #{updUser,jdbcType=VARCHAR}, #{updTime,jdbcType=TIMESTAMP}, #{updHost,jdbcType=VARCHAR}, 
-      #{batchNo,jdbcType=VARCHAR}, #{msg,jdbcType=LONGVARCHAR}, #{result,jdbcType=LONGVARCHAR}
-      )
+      #{batchNo,jdbcType=VARCHAR}, #{totalNumber,jdbcType=INTEGER}, #{msg,jdbcType=LONGVARCHAR}, 
+      #{result,jdbcType=LONGVARCHAR})
   </insert>
   <insert id="insertSelective" parameterType="com.freshport.entity.YwShipPortLogWithBLOBs">
     insert into yw_ship_port_log
@@ -81,6 +82,9 @@
       <if test="batchNo != null">
         batch_no,
       </if>
+      <if test="totalNumber != null">
+        total_number,
+      </if>
       <if test="msg != null">
         msg,
       </if>
@@ -119,6 +123,9 @@
       <if test="batchNo != null">
         #{batchNo,jdbcType=VARCHAR},
       </if>
+      <if test="totalNumber != null">
+        #{totalNumber,jdbcType=INTEGER},
+      </if>
       <if test="msg != null">
         #{msg,jdbcType=LONGVARCHAR},
       </if>
@@ -157,6 +164,9 @@
       <if test="batchNo != null">
         batch_no = #{batchNo,jdbcType=VARCHAR},
       </if>
+      <if test="totalNumber != null">
+        total_number = #{totalNumber,jdbcType=INTEGER},
+      </if>
       <if test="msg != null">
         msg = #{msg,jdbcType=LONGVARCHAR},
       </if>
@@ -177,6 +187,7 @@
       upd_time = #{updTime,jdbcType=TIMESTAMP},
       upd_host = #{updHost,jdbcType=VARCHAR},
       batch_no = #{batchNo,jdbcType=VARCHAR},
+      total_number = #{totalNumber,jdbcType=INTEGER},
       msg = #{msg,jdbcType=LONGVARCHAR},
       result = #{result,jdbcType=LONGVARCHAR}
     where yspl_id = #{ysplId,jdbcType=VARCHAR}
@@ -191,7 +202,8 @@
       upd_user = #{updUser,jdbcType=VARCHAR},
       upd_time = #{updTime,jdbcType=TIMESTAMP},
       upd_host = #{updHost,jdbcType=VARCHAR},
-      batch_no = #{batchNo,jdbcType=VARCHAR}
+      batch_no = #{batchNo,jdbcType=VARCHAR},
+      total_number = #{totalNumber,jdbcType=INTEGER}
     where yspl_id = #{ysplId,jdbcType=VARCHAR}
   </update>
 </mapper>
\ No newline at end of file
Index: jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/YwShipPortResultMapper.xml
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/YwShipPortResultMapper.xml	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/dao/Mapper/YwShipPortResultMapper.xml	(revision 33814)
@@ -28,12 +28,18 @@
     <result column="upd_host" jdbcType="VARCHAR" property="updHost" />
     <result column="actual_anchorage_time" jdbcType="TIMESTAMP" property="actualAnchorageTime" />
     <result column="business_no" jdbcType="VARCHAR" property="businessNo" />
+    <result column="status" jdbcType="VARCHAR" property="status" />
+    <result column="upd_status" jdbcType="VARCHAR" property="updStatus" />
+    <result column="grab_number" jdbcType="VARCHAR" property="grabNumber" />
+    <result column="eta_status" jdbcType="VARCHAR" property="etaStatus" />
+    <result column="new_eta_time" jdbcType="VARCHAR" property="newEtaTime" />
   </resultMap>
   <sql id="Base_Column_List">
     yspr_id, loading_number, container_number, expect_arrival_time, actual_port_time, 
     departure_port, transit_port, destination_port, ship_name, transit_ship_name, voyage, 
     transit_voyage, actual_sailing_time, unloading_port, approach_time, unloading_time, 
-    type, batch_no, crt_user, crt_time, crt_host, upd_user, upd_time, upd_host, actual_anchorage_time,business_no
+    type, batch_no, crt_user, crt_time, crt_host, upd_user, upd_time, upd_host, actual_anchorage_time, 
+    business_no, status, upd_status, grab_number
   </sql>
   <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
     select 
@@ -54,7 +60,9 @@
       approach_time, unloading_time, type, 
       batch_no, crt_user, crt_time, 
       crt_host, upd_user, upd_time, 
-      upd_host, actual_anchorage_time, business_no)
+      upd_host, actual_anchorage_time, business_no, 
+      status, upd_status, grab_number, eta_status
+      )
     values (#{ysprId,jdbcType=VARCHAR}, #{loadingNumber,jdbcType=VARCHAR}, #{containerNumber,jdbcType=VARCHAR}, 
       #{expectArrivalTime,jdbcType=TIMESTAMP}, #{actualPortTime,jdbcType=TIMESTAMP}, 
       #{departurePort,jdbcType=VARCHAR}, #{transitPort,jdbcType=VARCHAR}, #{destinationPort,jdbcType=VARCHAR}, 
@@ -63,27 +71,32 @@
       #{approachTime,jdbcType=TIMESTAMP}, #{unloadingTime,jdbcType=TIMESTAMP}, #{type,jdbcType=VARCHAR}, 
       #{batchNo,jdbcType=VARCHAR}, #{crtUser,jdbcType=VARCHAR}, #{crtTime,jdbcType=TIMESTAMP}, 
       #{crtHost,jdbcType=VARCHAR}, #{updUser,jdbcType=VARCHAR}, #{updTime,jdbcType=TIMESTAMP}, 
-      #{updHost,jdbcType=VARCHAR}, #{actualAnchorageTime,jdbcType=TIMESTAMP}, #{businessNo,jdbcType=VARCHAR})
+      #{updHost,jdbcType=VARCHAR}, #{actualAnchorageTime,jdbcType=TIMESTAMP}, #{businessNo,jdbcType=VARCHAR}, 
+      #{status,jdbcType=VARCHAR}, #{updStatus,jdbcType=VARCHAR}, #{grabNumber,jdbcType=VARCHAR}, #{etaStatus,jdbcType=VARCHAR}
+      )
   </insert>
   
   <insert id="insertList" parameterType="java.util.List">
-	  	insert into yw_ship_port_result (yspr_id, loading_number, container_number, 
-	      expect_arrival_time, actual_port_time, 
-	      departure_port, transit_port, destination_port, 
-	      ship_name, transit_ship_name, voyage, 
-	      transit_voyage, actual_sailing_time, unloading_port, 
-	      approach_time, unloading_time, type, 
-	      batch_no, crt_time, actual_anchorage_time, business_no)
-		 values
-		<foreach collection ="list" item="item" index= "index" separator =",">
-		    (#{item.ysprId,jdbcType=VARCHAR}, #{item.loadingNumber,jdbcType=VARCHAR}, #{item.containerNumber,jdbcType=VARCHAR}, 
-	      #{item.expectArrivalTime,jdbcType=TIMESTAMP}, #{item.actualPortTime,jdbcType=TIMESTAMP}, 
-	      #{item.departurePort,jdbcType=VARCHAR}, #{item.transitPort,jdbcType=VARCHAR}, #{item.destinationPort,jdbcType=VARCHAR}, 
-	      #{item.shipName,jdbcType=VARCHAR}, #{item.transitShipName,jdbcType=VARCHAR}, #{item.voyage,jdbcType=VARCHAR}, 
-	      #{item.transitVoyage,jdbcType=VARCHAR}, #{item.actualSailingTime,jdbcType=TIMESTAMP}, #{item.unloadingPort,jdbcType=VARCHAR}, 
-	      #{item.approachTime,jdbcType=TIMESTAMP}, #{item.unloadingTime,jdbcType=TIMESTAMP}, #{item.type,jdbcType=VARCHAR}, 
-	      #{item.batchNo,jdbcType=VARCHAR}, #{item.crtTime,jdbcType=TIMESTAMP}, #{item.actualAnchorageTime,jdbcType=TIMESTAMP}, #{item.businessNo,jdbcType=VARCHAR})
-		</foreach>
+    insert into yw_ship_port_result (yspr_id, loading_number, container_number, 
+       expect_arrival_time, actual_port_time, 
+       departure_port, transit_port, destination_port, 
+       ship_name, transit_ship_name, voyage, 
+       transit_voyage, actual_sailing_time, unloading_port, 
+       approach_time, unloading_time, type, 
+       batch_no, crt_time, actual_anchorage_time, business_no,
+       status, upd_status, grab_number, eta_status)
+   values
+  <foreach collection ="list" item="item" index= "index" separator =",">
+      (#{item.ysprId,jdbcType=VARCHAR}, #{item.loadingNumber,jdbcType=VARCHAR}, #{item.containerNumber,jdbcType=VARCHAR}, 
+       #{item.expectArrivalTime,jdbcType=TIMESTAMP}, #{item.actualPortTime,jdbcType=TIMESTAMP}, 
+       #{item.departurePort,jdbcType=VARCHAR}, #{item.transitPort,jdbcType=VARCHAR}, #{item.destinationPort,jdbcType=VARCHAR}, 
+       #{item.shipName,jdbcType=VARCHAR}, #{item.transitShipName,jdbcType=VARCHAR}, #{item.voyage,jdbcType=VARCHAR}, 
+       #{item.transitVoyage,jdbcType=VARCHAR}, #{item.actualSailingTime,jdbcType=TIMESTAMP}, #{item.unloadingPort,jdbcType=VARCHAR}, 
+       #{item.approachTime,jdbcType=TIMESTAMP}, #{item.unloadingTime,jdbcType=TIMESTAMP}, #{item.type,jdbcType=VARCHAR}, 
+       #{item.batchNo,jdbcType=VARCHAR}, #{item.crtTime,jdbcType=TIMESTAMP}, #{item.actualAnchorageTime,jdbcType=TIMESTAMP}, 
+       #{item.businessNo,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR}, #{item.updStatus,jdbcType=VARCHAR}, #{item.grabNumber,jdbcType=VARCHAR},
+       #{item.etaStatus,jdbcType=VARCHAR})
+  </foreach>
  </insert>
   
   <insert id="insertSelective" parameterType="com.freshport.entity.YwShipPortResult">
@@ -164,6 +177,18 @@
       <if test="actualAnchorageTime != null">
         actual_anchorage_time,
       </if>
+      <if test="businessNo != null">
+        business_no,
+      </if>
+      <if test="status != null">
+        status,
+      </if>
+      <if test="updStatus != null">
+        upd_status,
+      </if>
+      <if test="grabNumber != null">
+        grab_number,
+      </if>
     </trim>
     <trim prefix="values (" suffix=")" suffixOverrides=",">
       <if test="ysprId != null">
@@ -241,6 +266,18 @@
       <if test="actualAnchorageTime != null">
         #{actualAnchorageTime,jdbcType=TIMESTAMP},
       </if>
+      <if test="businessNo != null">
+        #{businessNo,jdbcType=VARCHAR},
+      </if>
+      <if test="status != null">
+        #{status,jdbcType=VARCHAR},
+      </if>
+      <if test="updStatus != null">
+        #{updStatus,jdbcType=VARCHAR},
+      </if>
+      <if test="grabNumber != null">
+        #{grabNumber,jdbcType=VARCHAR},
+      </if>
     </trim>
   </insert>
   <update id="updateByPrimaryKeySelective" parameterType="com.freshport.entity.YwShipPortResult">
@@ -318,6 +355,18 @@
       <if test="actualAnchorageTime != null">
         actual_anchorage_time = #{actualAnchorageTime,jdbcType=TIMESTAMP},
       </if>
+      <if test="businessNo != null">
+        business_no = #{businessNo,jdbcType=VARCHAR},
+      </if>
+      <if test="status != null">
+        status = #{status,jdbcType=VARCHAR},
+      </if>
+      <if test="updStatus != null">
+        upd_status = #{updStatus,jdbcType=VARCHAR},
+      </if>
+      <if test="grabNumber != null">
+        grab_number = #{grabNumber,jdbcType=VARCHAR},
+      </if>
     </set>
     where yspr_id = #{ysprId,jdbcType=VARCHAR}
   </update>
@@ -346,7 +395,45 @@
       upd_user = #{updUser,jdbcType=VARCHAR},
       upd_time = #{updTime,jdbcType=TIMESTAMP},
       upd_host = #{updHost,jdbcType=VARCHAR},
-      actual_anchorage_time = #{actualAnchorageTime,jdbcType=TIMESTAMP}
+      actual_anchorage_time = #{actualAnchorageTime,jdbcType=TIMESTAMP},
+      business_no = #{businessNo,jdbcType=VARCHAR},
+      status = #{status,jdbcType=VARCHAR},
+      upd_status = #{updStatus,jdbcType=VARCHAR},
+      grab_number = #{grabNumber,jdbcType=VARCHAR}
     where yspr_id = #{ysprId,jdbcType=VARCHAR}
   </update>
+  
+  <select  id="updateUpdStatusByBusinessNoList" parameterType="java.util.List">
+  	update yw_ship_port_result
+  	set upd_status = '1'
+  	where batch_no = #{batchNo}
+  		and business_no in 
+  		<foreach collection="list"  index="index" item="str"  open="(" separator="," close=")">
+			'${str}' 
+		</foreach>
+  </select>
+  
+  <select id="updateEtaStatusAndNewEtaTimeForShip" parameterType="java.util.List">
+  	<foreach collection="list" separator=";" item="item">
+  	  		update yw_ship_port_result
+    		<set> 
+		        	eta_status = '1',
+		        	new_eta_time = #{item.newExpectArrivalTime}
+		      </set>
+		    where business_no = #{item.businessNo}
+		    	and batch_no = #{item.batchNo}
+  	</foreach>
+  </select>
+  
+  <update id="updateUpdStatusAndNewEtaTimeForPort" parameterType="java.util.List">
+  		<foreach collection="list" separator=";" item="item">
+  	  		update yw_ship_port_result
+    		<set> 
+		        	upd_status = '1',
+		        	new_eta_time = #{item.newExpectArrivalTime}
+		      </set>
+		    where business_no = #{item.businessNo}
+		    	and batch_no = #{item.batchNo}
+  		</foreach>
+  </update>
 </mapper>
\ No newline at end of file
Index: jinan/trunk/yunna/src/main/java/com/freshport/dao/ShipPortMapper.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/dao/ShipPortMapper.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/dao/ShipPortMapper.java	(revision 33814)
@@ -116,7 +116,7 @@
 
     /**
      * 
-     * updateShipInfoListForHddz(更新货代单证表 船司信息- 中转港、是否中转、船名、航次、开船时间、预计靠港时间)       
+     * updateShipInfoListForHddz(更新货代单证表 船司信息- 中转港、是否中转、船名、航次、开船时间)       
      * @param list  
      * @return void  
      * @Exception 异常对象    
@@ -125,4 +125,15 @@
      */
     void updateShipInfoListForHddz(List<ShipForHddzVO> list);
 
+    /**
+     * 
+     * updateShipEtaListForHddz(更新货代单证-预计靠港时间)        
+     * @param list  
+     * @return void  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-27 11:10:28
+     */
+    void updateShipEtaListForHddz(List<ShipForHddzVO> list);
+
 }
\ No newline at end of file
Index: jinan/trunk/yunna/src/main/java/com/freshport/dao/YwShipPortLoadingMapper.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/dao/YwShipPortLoadingMapper.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/dao/YwShipPortLoadingMapper.java	(revision 33814)
@@ -33,4 +33,16 @@
      * @date 2023-03-21 17:10:37
      */
     String queryMaxSerialNumByType(@Param("dateStr") String dateStr);
+
+    /**
+     * 
+     * countByBatchNo(根据批次号统计提单号数据总量)       
+     * @param batchNo
+     * @return  
+     * @return int  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-27 14:29:59
+     */
+    int countByBatchNo(@Param("batchNo") String batchNo);
 }
\ No newline at end of file
Index: jinan/trunk/yunna/src/main/java/com/freshport/dao/YwShipPortResultMapper.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/dao/YwShipPortResultMapper.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/dao/YwShipPortResultMapper.java	(revision 33814)
@@ -2,20 +2,59 @@
 
 import java.util.List;
 
+import org.apache.ibatis.annotations.Param;
+
 import com.freshport.entity.YwShipPortResult;
+import com.freshport.entity.yunna.PortForHddzVO;
+import com.freshport.entity.yunna.ShipForHddzVO;
 
 public interface YwShipPortResultMapper {
     int deleteByPrimaryKey(String ysprId);
 
     int insert(YwShipPortResult record);
 
+    int insertSelective(YwShipPortResult record);
+
     int insertList(List<YwShipPortResult> list);
 
-    int insertSelective(YwShipPortResult record);
-
     YwShipPortResult selectByPrimaryKey(String ysprId);
 
     int updateByPrimaryKeySelective(YwShipPortResult record);
 
     int updateByPrimaryKey(YwShipPortResult record);
+
+    /**
+     * 
+     * updateUpdStatusByBusinessNoList(根据业务编号、批次号更新反写结果状态)        
+     * @param batchNo
+     * @param list
+     * @return  
+     * @return int  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-27 13:22:50
+     */
+    void updateUpdStatusByBusinessNoList(@Param("batchNo") String batchNo, @Param("list") List<String> list);
+
+    /**
+     * 
+     * updateEtaStatusAndNewEtaTimeForShip(船司-ETA更新状态和新ETA时间反写)       
+     * @param list  
+     * @return void  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-29 14:55:48
+     */
+    void updateEtaStatusAndNewEtaTimeForShip(@Param("list") List<ShipForHddzVO> list);
+
+    /**
+     * 
+     * updateUpdStatusAndNewEtaTimeForPort(港口-更新数据状态和新ETA时间反写)       
+     * @param list  
+     * @return void  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-29 15:16:26
+     */
+    void updateUpdStatusAndNewEtaTimeForPort(@Param("list") List<PortForHddzVO> list);
 }
\ No newline at end of file
Index: jinan/trunk/yunna/src/main/java/com/freshport/entity/YwShipPortLog.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/entity/YwShipPortLog.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/entity/YwShipPortLog.java	(revision 33814)
@@ -23,6 +23,8 @@
 
     private String batchNo;
 
+    private Integer totalNumber;
+
     public String getYsplId() {
         return ysplId;
     }
@@ -102,4 +104,12 @@
     public void setBatchNo(String batchNo) {
         this.batchNo = batchNo;
     }
+
+    public Integer getTotalNumber() {
+        return totalNumber;
+    }
+
+    public void setTotalNumber(Integer totalNumber) {
+        this.totalNumber = totalNumber;
+    }
 }
\ No newline at end of file
Index: jinan/trunk/yunna/src/main/java/com/freshport/entity/YwShipPortResult.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/entity/YwShipPortResult.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/entity/YwShipPortResult.java	(revision 33814)
@@ -55,6 +55,16 @@
 
     private String businessNo;
 
+    private String status;
+
+    private String updStatus;
+
+    private String grabNumber;
+
+    private String etaStatus;
+
+    private Date newEtaTime;
+
     public String getYsprId() {
         return ysprId;
     }
@@ -263,4 +273,44 @@
         this.businessNo = businessNo;
     }
 
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getUpdStatus() {
+        return updStatus;
+    }
+
+    public void setUpdStatus(String updStatus) {
+        this.updStatus = updStatus;
+    }
+
+    public String getGrabNumber() {
+        return grabNumber;
+    }
+
+    public void setGrabNumber(String grabNumber) {
+        this.grabNumber = grabNumber;
+    }
+
+    public String getEtaStatus() {
+        return etaStatus;
+    }
+
+    public void setEtaStatus(String etaStatus) {
+        this.etaStatus = etaStatus;
+    }
+
+    public Date getNewEtaTime() {
+        return newEtaTime;
+    }
+
+    public void setNewEtaTime(Date newEtaTime) {
+        this.newEtaTime = newEtaTime;
+    }
+
 }
\ No newline at end of file
Index: jinan/trunk/yunna/src/main/java/com/freshport/entity/yunna/PortForHddzVO.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/entity/yunna/PortForHddzVO.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/entity/yunna/PortForHddzVO.java	(revision 33814)
@@ -64,9 +64,9 @@
     private String hcorhbh;
 
     /**
-     *  航次
+     *  中转航次-水果通航次
      */
-    private String zZHcorhbh;
+    private String zzHcorhbh;
 
     /**
      *  hddz.mdg
@@ -81,6 +81,11 @@
     private Date expectArrivalTime;
 
     /**
+     * 比较后，新的ETA  更新货代单证用到
+     */
+    private Date newExpectArrivalTime;
+
+    /**
      *  实际靠港时间
      */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
Index: jinan/trunk/yunna/src/main/java/com/freshport/entity/yunna/ShipForHddzVO.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/entity/yunna/ShipForHddzVO.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/entity/yunna/ShipForHddzVO.java	(revision 33814)
@@ -64,17 +64,29 @@
      */
     private String mdg;
 
-    // 预计靠港时间
+    /**
+     *  预计靠港时间
+     */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date expectArrivalTime;
 
     /**
+     * 数据创建时间
+     */
+    private Date crtTime;
+
+    /**
      *  预计靠港时间-返回数据时间 相隔小时数
      */
     private Integer hours;
 
     /**
+     * 比较后，新的ETA  更新货代单证用到
+     */
+    private Date newExpectArrivalTime;
+
+    /**
      *  中转港
      */
     private String transitPort;
Index: jinan/trunk/yunna/src/main/java/com/freshport/entity/yunna/ShipPortResultVO.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/entity/yunna/ShipPortResultVO.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/entity/yunna/ShipPortResultVO.java	(revision 33814)
@@ -52,14 +52,14 @@
     /**
      *  预计靠港时间
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date expectArrivalTime;
 
     /**
      *  实际靠港时间
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date actualPortTime;
 
@@ -101,6 +101,8 @@
     /**
      *  ATD实际开船日期-清关新增
      */
+    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date actualSailingTime;
 
     /**
@@ -111,21 +113,21 @@
     /**
      *  进场时间
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date approachTime;
 
     /**
      *  卸船时间-xcsj
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date unloadingTime;
 
     /**
      *  上海实际抵锚时间
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date actualAnchorageTime;
 
@@ -134,4 +136,9 @@
      */
     private String batchNo;
 
+    /**
+     * 0：网站查到数据； 1：网站查到空数据；2:网站没查到；
+     */
+    private String status;
+
 }
Index: jinan/trunk/yunna/src/main/java/com/freshport/service/FruitShipPortService.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/service/FruitShipPortService.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/service/FruitShipPortService.java	(revision 33814)
@@ -11,8 +11,6 @@
 
 import java.util.List;
 
-import org.springframework.web.bind.annotation.RequestBody;
-
 import com.freshport.entity.yunna.LoadingNumberQueryParam;
 import com.freshport.entity.yunna.LoadingNumberResultVO;
 import com.freshport.entity.yunna.ShipPortResultVO;
@@ -43,7 +41,7 @@
      * @author lixd  
      * @date 2023-03-15 13:48:48
      */
-    List<LoadingNumberResultVO> queryLoadingNumberInfoList(@RequestBody LoadingNumberQueryParam params);
+    List<LoadingNumberResultVO> queryLoadingNumberInfoList(LoadingNumberQueryParam params);
 
     /**
      * 
@@ -73,39 +71,40 @@
      * @param msg
      * @param result
      * @param type
-     * @param remark  
+     * @param totalNumber  
      * @param batchNo  
      * @return void  
      * @Exception 异常对象    
      * @author lixd  
      * @date 2023-03-15 14:14:35
      */
-    void saveShipPortLog(String msg, String result, String type, String remark, String batchNo);
+    void saveShipPortLog(String msg, String result, String type, Integer totalNumber, String batchNo);
 
     /**
      * 
      * saveShipPortLoading(保存原始提单号数据)     
      * @param list
-     * @param batchNo  
      * @param type  
+     * @param batchNo 
      * @return void  
      * @Exception 异常对象    
      * @author lixd  
      * @date 2023-03-16 13:45:59
      */
-    void saveShipPortLoading(List<LoadingNumberResultVO> list, String batchNo, String type);
+    void saveShipPortLoading(List<LoadingNumberResultVO> list, String type, String batchNo);
 
     /**
      * 
      * saveShipPortResult(保存回传船司/港口结果)     
      * @param list  
-     * @param type  
+     * @param type 
+     * @param batchNo  
      * @return void  
      * @Exception 异常对象    
      * @author lixd  
      * @date 2023-03-17 09:35:10
      */
-    void saveShipPortResult(List<ShipPortResultVO> list, String type);
+    void saveShipPortResult(List<ShipPortResultVO> list, String type, String batchNo);
 
     /**
      * 
@@ -129,4 +128,29 @@
      */
     void savePortInfo(List<ShipPortResultVO> params);
 
+    /**
+     * 
+     * saveShipPortError(保存异常日志)       
+     * @param errorCode
+     * @param batchNo
+     * @param msg  
+     * @return void  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-27 14:06:18
+     */
+    void saveShipPortError(String errorCode, String batchNo, String msg);
+
+    /**
+     * 
+     * savePortOrShipInfo(手动处理单条船司/港口信息-重新反写数据)      
+     * @param type
+     * @param batchNo  
+     * @return void  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-28 15:41:37
+     */
+    void savePortOrShipInfo(String type, String batchNo);
+
 }
Index: jinan/trunk/yunna/src/main/java/com/freshport/service/PortService.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/service/PortService.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/service/PortService.java	(revision 33814)
@@ -76,13 +76,24 @@
 
     /**
      * 
-     * updateJzxhInfoForPort(更新集装箱号表港口相关字段信息-卸船时间)      
+     * updateContainerNoInfoForPort(更新集装箱号表港口相关字段信息-卸船时间)      
      * @param list  
      * @return void  
      * @Exception 异常对象    
      * @author lixd  
      * @date 2023-03-17 15:55:48
      */
-    void updateJzxhInfoForPort(List<PortForHddzVO> list);
+    void updateContainerNoInfoForPort(List<PortForHddzVO> list);
 
+    /**
+     * 
+     * updatePortResultUpdStatus(更新港口结果反写状态)       
+     * @param list  
+     * @return void  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-27 13:35:42
+     */
+    void updatePortResultUpdStatus(List<PortForHddzVO> list);
+
 }
Index: jinan/trunk/yunna/src/main/java/com/freshport/service/ShipService.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/service/ShipService.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/service/ShipService.java	(revision 33814)
@@ -67,11 +67,47 @@
      * 
      * updateHddzInfoForShip(更新货代单证表船司信息)       
      * @param list  
+     * @param ywbhStrList  
      * @return void  
      * @Exception 异常对象    
      * @author lixd  
      * @date 2023-03-20 13:44:52
      */
-    void updateHddzInfoForShip(List<ShipForHddzVO> list);
+    void updateHddzInfoForShip(List<ShipForHddzVO> list, List<String> ywbhStrList);
 
+    /**
+     * 
+     * updateHddzEtaForShip(更新货代单证-ETA(预计靠港时间))        
+     * @param list  
+     * @param etaStatusList  
+     * @return void  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-27 10:11:51
+     */
+    void updateHddzEtaForShip(List<ShipForHddzVO> list, List<ShipForHddzVO> etaStatusList);
+
+    /**
+     * 
+     * updateShipResultEtaStatus(船司ETA更新状态)       
+     * @param etaStatusList  
+     * @return void  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-29 14:53:46
+     */
+    void updateShipResultEtaStatus(List<ShipForHddzVO> etaStatusList);
+
+    /**
+     * 
+     * updateShipResultUpdStatus(更新船司结果反写状态)       
+     * @param list
+     * @param batchNo  
+     * @return void  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-27 13:14:27
+     */
+    void updateShipResultUpdStatus(List<String> list, String batchNo);
+
 }
Index: jinan/trunk/yunna/src/main/java/com/freshport/service/impl/FruitShipPortServiceImpl.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/service/impl/FruitShipPortServiceImpl.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/service/impl/FruitShipPortServiceImpl.java	(revision 33814)
@@ -15,17 +15,21 @@
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
+import java.util.concurrent.ThreadPoolExecutor;
 
 import javax.annotation.Resource;
 
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import com.alibaba.fastjson.JSONObject;
+import com.freshport.dao.YwShipPortErrorMapper;
 import com.freshport.dao.YwShipPortLoadingMapper;
 import com.freshport.dao.YwShipPortLogMapper;
 import com.freshport.dao.YwShipPortResultMapper;
+import com.freshport.entity.YwShipPortError;
 import com.freshport.entity.YwShipPortLoading;
 import com.freshport.entity.YwShipPortLogWithBLOBs;
 import com.freshport.entity.YwShipPortResult;
@@ -82,47 +86,64 @@
     private YwShipPortLoadingMapper ywShipPortLoadingMapper;
 
     @Resource
+    private YwShipPortErrorMapper ywShipPortErrorMapper;
+
+    @Resource
     private RedisTemplate redisTemplate;
 
+    @Autowired
+    private ThreadPoolExecutor threadPoolExecutor;
+
     // @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
     @Override
     public List<LoadingNumberResultVO> queryLoadingNumberInfoList(LoadingNumberQueryParam params) {
 
         List<LoadingNumberResultVO> result = new ArrayList<LoadingNumberResultVO>();
-        String batchNo = "";
 
-        if (CommonInfo.TYPE_SHIP.equals(params.getType())) {
+        try {
+            if (CommonInfo.TYPE_SHIP.equals(params.getType())) {
 
-            result = shipService.queryLoadingNumberInfoList();
-        } else if (CommonInfo.TYPE_SHIP_TMP.equals(params.getType())) {
+                result = shipService.queryLoadingNumberInfoList();
+            } else if (CommonInfo.TYPE_SHIP_TMP.equals(params.getType())) {
 
-            result = shipService.queryLoadingNumberInfoListForTmp();
-        } else if (CommonInfo.TYPE_PORT.equals(params.getType())) {
+                result = shipService.queryLoadingNumberInfoListForTmp();
+            } else if (CommonInfo.TYPE_PORT.equals(params.getType())) {
 
-            result = portService.queryLoadingNumberInfoList();
-        } else if (CommonInfo.TYPE_PORT_TMP.equals(params.getType())) {
+                result = portService.queryLoadingNumberInfoList();
+            } else if (CommonInfo.TYPE_PORT_TMP.equals(params.getType())) {
 
-            result = portService.queryLoadingNumberInfoListForTmp();
+                result = portService.queryLoadingNumberInfoListForTmp();
+            }
+        } catch (Exception e) {
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PROGRAM, "",
+                        "查询提单号信息-程序异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
-        log.debug("===============查询提单号类型：{}, 返回结果条数：{}", params.getType(), result.size());
+        log.info("===============查询提单号类型：{}, 返回结果条数：{}", params.getType(), result.size());
 
         if (!CommonUtils.isEmpty(result) && result.size() > 0) {
 
+            String batchNo = "";
+            String type = "";
             if (CommonInfo.TYPE_SHIP.equals(params.getType()) || CommonInfo.TYPE_SHIP_TMP.equals(params.getType())) {
                 batchNo = getShipPortNoFromRedis(CommonInfo.TYPE_SHIP);
+                type = CommonInfo.TYPE_SHIP;
             } else if (CommonInfo.TYPE_PORT.equals(params.getType())
                     || CommonInfo.TYPE_PORT_TMP.equals(params.getType())) {
                 batchNo = getShipPortNoFromRedis(CommonInfo.TYPE_PORT);
+                type = CommonInfo.TYPE_PORT;
             }
-            log.debug("===============生成批次号：{}", batchNo);
-            // String batchNo = UUID.randomUUID().toString();
+            log.info("===============生成批次号：{}", batchNo);
 
             for (LoadingNumberResultVO vo : result) {
                 vo.setBatchNo(batchNo);
             }
 
             // 保存传过去原始提单号数据
-            fruitShipPortService.saveShipPortLoading(result, batchNo, params.getType());
+            fruitShipPortService.saveShipPortLoading(result, type, batchNo);
         }
 
         return result;
@@ -130,104 +151,204 @@
 
     @Transactional
     @Override
-    public void saveShipPortLoading(List<LoadingNumberResultVO> list, String batchNo, String type) {
+    public void saveShipPortLoading(List<LoadingNumberResultVO> list, String type, String batchNo) {
         List<YwShipPortLoading> loadingList = new ArrayList<YwShipPortLoading>();
         Date crtTime = new Date();
         for (LoadingNumberResultVO vo : list) {
-            YwShipPortLoading lad = new YwShipPortLoading();
-            lad.setYsplId(UUID.randomUUID().toString());
-            lad.setBatchNo(batchNo);
-            lad.setLoadingNumber(vo.getLoadingNumber());
-            lad.setContainerNumber(vo.getContainerNumber());
-            lad.setBusinessNo(vo.getBusinessNo());
-            lad.setType(type);
-            lad.setDestinationPort(vo.getDestinationPort());
-            lad.setShipName(vo.getShipName());
-            lad.setTransitShipName(vo.getTransitShipName());
-            lad.setFirmName(vo.getFirmName());
+            YwShipPortLoading lad = createShipPortLoading(type, vo);
             lad.setCrtTime(crtTime);
             loadingList.add(lad);
         }
 
-        if (!CommonUtils.isEmpty(loadingList) && loadingList.size() > 0) {
-            // 分组保存
-            List<List<YwShipPortLoading>> splitList = CommonUtils.splitList(loadingList,
-                    CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED_190);
-            for (int i = 0; i < splitList.size(); i++) {
-                ywShipPortLoadingMapper.insertList(splitList.get(i));
+        try {
+            if (!CommonUtils.isEmpty(loadingList) && loadingList.size() > 0) {
+                // 分组保存
+                List<List<YwShipPortLoading>> splitList = CommonUtils.splitList(loadingList,
+                        CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED_150);
+                for (int i = 0; i < splitList.size(); i++) {
+                    ywShipPortLoadingMapper.insertList(splitList.get(i));
+                }
             }
+        } catch (Exception e) {
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, batchNo,
+                        "保存yw_ship_port_loading-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
     }
 
+    /**
+     * 
+     * createShipPortLoading(创建提单号查询结果信息)    
+     * @param type
+     * @param vo
+     * @return  
+     * @return YwShipPortLoading  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-27 09:46:36
+     */
+    private YwShipPortLoading createShipPortLoading(String type, LoadingNumberResultVO vo) {
+        YwShipPortLoading lad = new YwShipPortLoading();
+        lad.setYsplId(UUID.randomUUID().toString());
+        lad.setBatchNo(vo.getBatchNo());
+        lad.setLoadingNumber(vo.getLoadingNumber());
+        lad.setContainerNumber(vo.getContainerNumber());
+        lad.setBusinessNo(vo.getBusinessNo());
+        lad.setType(type);
+        lad.setDestinationPort(vo.getDestinationPort());
+        lad.setShipName(vo.getShipName());
+        lad.setTransitShipName(vo.getTransitShipName());
+        lad.setFirmName(vo.getFirmName());
+        return lad;
+    }
+
     @Transactional
     @Override
-    public void saveShipPortLog(String msg, String result, String type, String remark, String batchNo) {
+    public void saveShipPortLog(String msg, String result, String type, Integer totalNumber, String batchNo) {
         YwShipPortLogWithBLOBs log = new YwShipPortLogWithBLOBs();
         log.setYsplId(UUID.randomUUID().toString());
         log.setMsg(msg);
         log.setResult(result);
-        log.setType(type);
-        log.setRemark(remark);
+        if (type.contains(CommonInfo.TYPE_SHIP)) {
+            log.setType(CommonInfo.LOG_TYPE_LOADING_SHIP);
+        } else if (type.contains(CommonInfo.TYPE_PORT)) {
+            log.setType(CommonInfo.LOG_TYPE_LOADING_PORT);
+        } else {
+            log.setType(type);
+        }
+        log.setTotalNumber(totalNumber);
         log.setBatchNo(batchNo);
         log.setCrtTime(new Date());
 
-        ywShipPortLogMapper.insert(log);
+        try {
+            ywShipPortLogMapper.insert(log);
+        } catch (Exception e) {
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, batchNo,
+                        "保存yw_ship_port_log-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
     }
 
     @Transactional
     @Override
-    public void saveShipPortResult(List<ShipPortResultVO> list, String type) {
+    public void saveShipPortResult(List<ShipPortResultVO> list, String type, String batchNo) {
         List<YwShipPortResult> resultList = new ArrayList<YwShipPortResult>();
         Date crtTime = new Date();
         for (ShipPortResultVO vo : list) {
-            YwShipPortResult rs = new YwShipPortResult();
-            rs.setYsprId(UUID.randomUUID().toString());
-            rs.setType(type);
-            rs.setBatchNo(vo.getBatchNo());
-            rs.setLoadingNumber(vo.getLoadingNumber());
-            rs.setContainerNumber(vo.getContainerNumber());
-            rs.setBusinessNo(vo.getBusinessNo());
-            rs.setExpectArrivalTime(vo.getExpectArrivalTime());
-            rs.setActualPortTime(vo.getActualPortTime());
-            rs.setActualSailingTime(vo.getActualSailingTime());
-            rs.setApproachTime(vo.getApproachTime());
-            rs.setActualAnchorageTime(vo.getActualAnchorageTime());
-            rs.setUnloadingTime(vo.getUnloadingTime());
-            rs.setUnloadingPort(vo.getUnloadingPort());
-            rs.setDeparturePort(vo.getDeparturePort());
-            rs.setDestinationPort(vo.getDestinationPort());
-            rs.setTransitPort(vo.getTransitPort());
-            rs.setShipName(vo.getShipName());
-            rs.setTransitShipName(vo.getTransitShipName());
-            rs.setVoyage(vo.getVoyage());
-            rs.setTransitVoyage(vo.getTransitVoyage());
+            YwShipPortResult rs = createShipPortResult(type, vo);
+            rs.setCrtTime(crtTime);
 
-            rs.setCrtTime(crtTime);
             resultList.add(rs);
         }
 
-        if (!CommonUtils.isEmpty(resultList) && resultList.size() > 0) {
-            // 分组保存
-            List<List<YwShipPortResult>> splitList = CommonUtils.splitList(resultList,
-                    CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
-            for (int i = 0; i < splitList.size(); i++) {
-                ywShipPortResultMapper.insertList(splitList.get(i));
+        try {
+            if (!CommonUtils.isEmpty(resultList) && resultList.size() > 0) {
+                // 分组保存
+                List<List<YwShipPortResult>> splitList = CommonUtils.splitList(resultList,
+                        CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED_80);
+                for (int i = 0; i < splitList.size(); i++) {
+                    ywShipPortResultMapper.insertList(splitList.get(i));
+                }
             }
+        } catch (Exception e) {
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, batchNo,
+                        "保存yw_ship_port_result-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
     }
 
+    /**
+     * 
+     * createShipPortResult(创建回传结果信息)       
+     * @param type
+     * @param vo
+     * @return  
+     * @return YwShipPortResult  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-27 09:44:08
+     */
+    private YwShipPortResult createShipPortResult(String type, ShipPortResultVO vo) {
+        YwShipPortResult rs = new YwShipPortResult();
+        rs.setYsprId(UUID.randomUUID().toString());
+        rs.setType(type);
+        rs.setBatchNo(vo.getBatchNo());
+        rs.setLoadingNumber(vo.getLoadingNumber());
+        rs.setContainerNumber(vo.getContainerNumber());
+        rs.setBusinessNo(vo.getBusinessNo());
+        rs.setExpectArrivalTime(vo.getExpectArrivalTime());
+        rs.setActualPortTime(vo.getActualPortTime());
+        rs.setActualSailingTime(vo.getActualSailingTime());
+        rs.setApproachTime(vo.getApproachTime());
+        rs.setActualAnchorageTime(vo.getActualAnchorageTime());
+        rs.setUnloadingTime(vo.getUnloadingTime());
+        rs.setUnloadingPort(vo.getUnloadingPort());
+        rs.setDeparturePort(vo.getDeparturePort());
+        rs.setDestinationPort(vo.getDestinationPort());
+        rs.setTransitPort(vo.getTransitPort());
+        rs.setShipName(vo.getShipName());
+        rs.setTransitShipName(vo.getTransitShipName());
+        rs.setVoyage(vo.getVoyage());
+        rs.setTransitVoyage(vo.getTransitVoyage());
+        rs.setStatus(vo.getStatus());
+        // 默认未更新
+        rs.setUpdStatus(CommonInfo.COMMON_N_CODE);
+        rs.setEtaStatus(CommonInfo.COMMON_N_CODE);
+        if (CommonInfo.TYPE_PORT.equals(type)) {
+            rs.setGrabNumber("按分钟抓");
+        } else {
+            rs.setGrabNumber("8点,16点");
+        }
+
+        return rs;
+    }
+
     @Override
     public void saveShipInfo(List<ShipPortResultVO> result) {
 
+        log.info("======================回传船司结果，总条数：{}", result.size());
         if (!CommonUtils.isEmpty(result) && result.size() > 0) {
 
             String batchNo = result.get(0).getBatchNo();
 
+            // 判断数据量是否一致，不一致放入异常信息表
+            int loadingNum = ywShipPortLoadingMapper.countByBatchNo(batchNo);
+            if (loadingNum != result.size()) {
+                try {
+                    fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_SHIP_NUM, batchNo,
+                            "船司数量异常：(推送数量" + loadingNum + " 返回数量" + result.size() + ")");
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+                }
+            }
+
             // 1. 保存原始数据表
-            fruitShipPortService.saveShipPortResult(result, CommonInfo.TYPE_SHIP);
+            fruitShipPortService.saveShipPortResult(result, CommonInfo.TYPE_SHIP, batchNo);
 
             // 2. 预警 / 反写
-            shipService.updateHddzAndWarnningInfo(batchNo);
+            threadPoolExecutor.execute(new Runnable() {
+
+                @Override
+                public void run() {
+
+                    try {
+                        shipService.updateHddzAndWarnningInfo(batchNo);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PROGRAM, batchNo,
+                                "回传船司-反写货代单证信息-程序异常：" + e.getMessage());
+                    }
+                }
+            });
         }
     }
 
@@ -238,11 +359,35 @@
 
             String batchNo = result.get(0).getBatchNo();
 
+            // 判断数据量是否一致，不一致放入异常信息表
+            int loadingNum = ywShipPortLoadingMapper.countByBatchNo(batchNo);
+            if (loadingNum != result.size()) {
+                try {
+                    fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PORT_NUM, batchNo,
+                            "港口数量异常：(推送数量" + loadingNum + " 返回数量" + result.size() + ")");
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+                }
+            }
+
             // 1. 保存原始数据表
-            fruitShipPortService.saveShipPortResult(result, CommonInfo.TYPE_PORT);
+            fruitShipPortService.saveShipPortResult(result, CommonInfo.TYPE_PORT, batchNo);
 
-            // 2. 预警 / 反写
-            portService.updateHddzAndWarnningInfo(batchNo);
+            // 2. 预警 / 反写 异步 TODO 上线前三天不更新，比对数据
+            threadPoolExecutor.execute(new Runnable() {
+
+                @Override
+                public void run() {
+
+                    try {
+                        portService.updateHddzAndWarnningInfo(batchNo);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_PROGRAM, batchNo,
+                                "回传港口-反写货代单证信息-程序异常：" + e.getMessage());
+                    }
+                }
+            });
         }
     }
 
@@ -266,11 +411,18 @@
                 }
 
                 serialNum = prefix + dataStr + String.format("%0" + CommonInfo.SHIP_PORT_NUM + "d", codeInt);
+            }
 
+        } catch (Exception e) {
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, "",
+                        "生成Redis批次号失败-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
             }
 
-        } catch (Exception e) {
-            throw new BaseException("getCostSqdbhFromRedis_error", "生成账单编号失败");
+            // TODO 是否要抛出异常？
+            throw new BaseException("getShipPortNoFromRedis_error", "生成批次号失败");
         }
 
         return serialNum;
@@ -334,4 +486,39 @@
         }
     }
 
+    @Transactional
+    @Override
+    public void saveShipPortError(String errorCode, String batchNo, String msg) {
+        YwShipPortError error = new YwShipPortError();
+        error.setId(UUID.randomUUID().toString());
+        error.setBatchNo(batchNo);
+        error.setErrorCode(errorCode);
+        error.setCrtTime(new Date());
+        if (msg.length() > 1000) {
+            error.setMsg(msg.substring(0, 1000));
+        } else {
+            error.setMsg(msg);
+        }
+
+        try {
+            ywShipPortErrorMapper.insert(error);
+        } catch (Exception e) {
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, batchNo,
+                        "保存yw_ship_port_error-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    @Override
+    public void savePortOrShipInfo(String type, String batchNo) {
+        if (CommonInfo.TYPE_SHIP.equals(type)) {
+            shipService.updateHddzAndWarnningInfo(batchNo);
+        } else if (CommonInfo.TYPE_PORT.equals(type)) {
+            portService.updateHddzAndWarnningInfo(batchNo);
+        }
+    }
+
 }
Index: jinan/trunk/yunna/src/main/java/com/freshport/service/impl/PortServiceImpl.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/service/impl/PortServiceImpl.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/service/impl/PortServiceImpl.java	(revision 33814)
@@ -22,8 +22,10 @@
 import org.springframework.transaction.annotation.Transactional;
 
 import com.freshport.dao.ShipPortMapper;
+import com.freshport.dao.YwShipPortResultMapper;
 import com.freshport.entity.yunna.LoadingNumberResultVO;
 import com.freshport.entity.yunna.PortForHddzVO;
+import com.freshport.service.FruitShipPortService;
 import com.freshport.service.PortService;
 import com.freshport.util.CommonInfo;
 import com.freshport.util.CommonUtils;
@@ -53,8 +55,14 @@
     private PortService portService;
 
     @Resource
+    private FruitShipPortService fruitShipPortService;
+
+    @Resource
     private ShipPortMapper shipPortMapper;
 
+    @Resource
+    private YwShipPortResultMapper ywShipPortResultMapper;
+
     @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
     @Override
     public List<LoadingNumberResultVO> queryLoadingNumberInfoList() {
@@ -69,43 +77,66 @@
 
     /**
      *  港口查询到的航次是反写水果通规则：如果水果通里航次有值就直接反写航次，如果水果通航次无值就直接反写提单航次/航班号 字段；
-     *  卸货港区：做映射表后对就反写，没有的就预警出来追加
+     *  卸货港区：做映射表后对就反写，没有的就预警出来追加(放bi了)
      */
     @Override
     public void updateHddzAndWarnningInfo(String batchNo) {
 
         List<PortForHddzVO> baseDataList = shipPortMapper.listPortInfoForHddz(batchNo);
-        log.debug("===========PORT-batchNo={}, 总list.size={}", batchNo, baseDataList.size());
+        log.info("===========PORT-batchNo={}, 总list.size={}", batchNo, baseDataList.size());
 
-        // TODO 预警数量是否一致
-
-        // TODO 预警: 卸货港区, 做映射表后对就反写，没有的就预警出来追加 映射表未添加
-        List<PortForHddzVO> noUnloadingPortList = baseDataList.stream()
-                .filter(vo -> CommonUtils.isEmpty(vo.getUnloadingPortCode())).collect(Collectors.toList());
-        log.debug("=================水果通xhgq没有值(未映射到)的数据有{}条", noUnloadingPortList.size());
-
         List<PortForHddzVO> withUnloadingPortList = baseDataList.stream()
                 .filter(vo -> !CommonUtils.isEmpty(vo.getUnloadingPortCode())).collect(Collectors.toList());
-        log.debug("=================水果通映射到xhgq的数据有{}条", withUnloadingPortList.size());
+        log.info("=================水果通映射到xhgq的数据有{}条", withUnloadingPortList.size());
+
         // 获取符合更新条件的数据，更新港口信息
-        if (!CommonUtils.isEmpty(withUnloadingPortList) && withUnloadingPortList.size() > 0) {
+        if (!CommonUtils.isEmpty(baseDataList) && baseDataList.size() > 0) {
 
-            for (PortForHddzVO vo : withUnloadingPortList) {
+            for (PortForHddzVO vo : baseDataList) {
 
-                // 目的港为上海，处理ETA和上海实际抵锚时间
+                // 目的港为上海，处理ETA和上海实际抵锚时间 ETA和抵锚时间，两个取最晚的时间
                 if (CommonInfo.PORT_SH.equals(vo.getDestinationPort())) {
-                    vo.setExpectArrivalTime(handleActualAnchorageTime(vo));
+                    vo.setNewExpectArrivalTime(handleActualAnchorageTime(vo));
+                } else {
+                    vo.setNewExpectArrivalTime(vo.getExpectArrivalTime());
                 }
             }
 
             // 1. 更新货代单证表港口相关字段信息
-            portService.updateHddzInfoForPort(withUnloadingPortList);
+            portService.updateHddzInfoForPort(baseDataList);
 
             // 2. 更新集装箱表港口相关信息
-            portService.updateJzxhInfoForPort(withUnloadingPortList);
+            portService.updateContainerNoInfoForPort(baseDataList);
+
+            // 3. 批量修改回传结果表数据反写状态
+            portService.updatePortResultUpdStatus(baseDataList);
         }
     }
 
+    @Transactional
+    @Override
+    public void updatePortResultUpdStatus(List<PortForHddzVO> list) {
+
+        try {
+            if (!CommonUtils.isEmpty(list) && list.size() > 0) {
+                // 分组保存
+                List<List<PortForHddzVO>> splitList = CommonUtils.splitList(list,
+                        CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
+                for (int i = 0; i < splitList.size(); i++) {
+                    ywShipPortResultMapper.updateUpdStatusAndNewEtaTimeForPort(splitList.get(i));
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, "",
+                        "更新yw_ship_port_result港口upd_status和new_eta_time反写状态-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
     /**
      * 
      * handleActualAnchorageTime(处理上海 预计靠港时间 和抵锚时间的关系)     
@@ -119,7 +150,7 @@
      * @author lixd  
      * @date 2023-03-20 09:53:43
      */
-    private Date handleActualAnchorageTime(PortForHddzVO vo) {
+    private static Date handleActualAnchorageTime(PortForHddzVO vo) {
 
         // 上海实际抵锚地时间为空，ETA = ETA
         if (CommonUtils.isEmpty(vo.getActualAnchorageTime())) {
@@ -175,9 +206,10 @@
                 ywbhVo.setLoadingNumber(list0.getLoadingNumber());
                 ywbhVo.setBusinessNo(list0.getBusinessNo());
                 ywbhVo.setExpectArrivalTime(list0.getExpectArrivalTime());
+                ywbhVo.setNewExpectArrivalTime(list0.getNewExpectArrivalTime());
                 ywbhVo.setActualPortTime(list0.getActualPortTime());
                 ywbhVo.setVoyage(list0.getVoyage());
-                ywbhVo.setZZHcorhbh(list0.getZZHcorhbh());
+                ywbhVo.setZzHcorhbh(list0.getZzHcorhbh());
                 ywbhVo.setUnloadingPort(list0.getUnloadingPort());
                 ywbhVo.setUnloadingPortShortName(list0.getUnloadingPortShortName());
                 ywbhVo.setUnloadingPortFullName(list0.getUnloadingPortFullName());
@@ -188,24 +220,39 @@
         }
 
         log.info("=======================符合更新yw_hddz表港口信息条件的有{}条", ywbhList.size());
-        // 根据业务编号更新ATA、ETA、航次、卸货港区
-        if (!CommonUtils.isEmpty(ywbhList) && ywbhList.size() > 0) {
-            // 分组保存
-            List<List<PortForHddzVO>> splitList = CommonUtils.splitList(ywbhList,
-                    CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
-            for (int i = 0; i < splitList.size(); i++) {
-                shipPortMapper.updatePortInfoListForHddz(splitList.get(i));
+        try {
+            // 根据业务编号更新ATA、ETA、航次、卸货港区
+            if (!CommonUtils.isEmpty(ywbhList) && ywbhList.size() > 0) {
+                // 分组保存
+                List<List<PortForHddzVO>> splitList = CommonUtils.splitList(ywbhList,
+                        CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
+                for (int i = 0; i < splitList.size(); i++) {
+                    shipPortMapper.updatePortInfoListForHddz(splitList.get(i));
+                }
             }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, "",
+                        "反写yw_hddz港口信息-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
     }
 
     @Transactional
     @Override
-    public void updateJzxhInfoForPort(List<PortForHddzVO> baseDataList) {
+    public void updateContainerNoInfoForPort(List<PortForHddzVO> baseDataList) {
         List<PortForHddzVO> jzxhList = new ArrayList<PortForHddzVO>();
-        //
+
+        List<PortForHddzVO> withUnloadingTimeList = baseDataList.stream()
+                .filter(vo -> !CommonUtils.isEmpty(vo.getUnloadingTime())).collect(Collectors.toList());
+        log.info("=================有卸船时间的数据有{}条", withUnloadingTimeList.size());
+
         // 根据业务编号+集装箱号分组 ywbh|jzxh
-        Map<String, List<PortForHddzVO>> basicMap = baseDataList.stream()
+        Map<String, List<PortForHddzVO>> basicMap = withUnloadingTimeList.stream()
                 .collect(Collectors.groupingBy(e -> (e.getBusinessNo() + "|" + e.getContainerNumber())));
         for (Map.Entry<String, List<PortForHddzVO>> entry : basicMap.entrySet()) {
 
@@ -227,14 +274,24 @@
         }
 
         log.info("=======================符合更新yw_hddz_jzxxx表港口信息条件的有{}条", jzxhList.size());
-        // 根据业务编号+集装箱号更新卸船时间
-        if (!CommonUtils.isEmpty(jzxhList) && jzxhList.size() > 0) {
-            // 分组保存
-            List<List<PortForHddzVO>> splitList = CommonUtils.splitList(jzxhList,
-                    CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
-            for (int i = 0; i < splitList.size(); i++) {
-                shipPortMapper.updatePortInfoListForJzxh(splitList.get(i));
+        try {
+            // 根据业务编号+集装箱号更新卸船时间
+            if (!CommonUtils.isEmpty(jzxhList) && jzxhList.size() > 0) {
+                // 分组保存
+                List<List<PortForHddzVO>> splitList = CommonUtils.splitList(jzxhList,
+                        CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
+                for (int i = 0; i < splitList.size(); i++) {
+                    shipPortMapper.updatePortInfoListForJzxh(splitList.get(i));
+                }
             }
+        } catch (Exception e) {
+            e.printStackTrace();
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, "",
+                        "反写yw_hddz_jzxxx港口信息-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
     }
 
Index: jinan/trunk/yunna/src/main/java/com/freshport/service/impl/ShipServiceImpl.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/service/impl/ShipServiceImpl.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/service/impl/ShipServiceImpl.java	(revision 33814)
@@ -10,8 +10,10 @@
 package com.freshport.service.impl;
 
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import javax.annotation.Resource;
@@ -20,12 +22,16 @@
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
+import com.alibaba.fastjson.JSONObject;
 import com.freshport.dao.ShipPortMapper;
+import com.freshport.dao.YwShipPortResultMapper;
 import com.freshport.entity.yunna.LoadingNumberResultVO;
 import com.freshport.entity.yunna.ShipForHddzVO;
+import com.freshport.service.FruitShipPortService;
 import com.freshport.service.ShipService;
 import com.freshport.util.CommonInfo;
 import com.freshport.util.CommonUtils;
+import com.freshport.util.DateUtils;
 
 import lombok.extern.slf4j.Slf4j;
 
@@ -51,8 +57,14 @@
     private ShipPortMapper shipPortMapper;
 
     @Resource
+    private YwShipPortResultMapper ywShipPortResultMapper;
+
+    @Resource
     private ShipService shipService;
 
+    @Resource
+    private FruitShipPortService fruitShipPortService;
+
     @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
     @Override
     public List<LoadingNumberResultVO> queryLoadingNumberInfoList() {
@@ -67,34 +79,194 @@
 
     @Override
     public void updateHddzAndWarnningInfo(String batchNo) {
+
         List<ShipForHddzVO> baseDataList = shipPortMapper.listShipInfoForHddz(batchNo);
-        log.debug("===========SHIP-batchNo={}, 总list.size={}", batchNo, baseDataList.size());
+        log.info("===========SHIP-batchNo={}, 总list.size={}", batchNo, baseDataList.size());
+        // 要更新回写状态的业务编号list
+        List<String> totalBusinessNoStrList = new ArrayList<String>();
+        List<ShipForHddzVO> etaStatusList = new ArrayList<ShipForHddzVO>();
 
-        // TODO 预警:
-        List<ShipForHddzVO> notSameShipList = baseDataList.stream().filter(
-                vo -> !vo.getShipName().equals(vo.getLadingShipName()) || !vo.getDestinationPort().equals(vo.getMdg()))
-                .collect(Collectors.toList());
-        log.debug("=================云纳船名/目的港和水果通目的港/提单船名不一致的的数据有{}条", notSameShipList.size());
-
         List<ShipForHddzVO> sameShipList = baseDataList.stream().filter(
                 vo -> vo.getShipName().equals(vo.getLadingShipName()) && vo.getDestinationPort().equals(vo.getMdg()))
                 .collect(Collectors.toList());
-        log.debug("=================云纳船名/目的港和水果通目的港/提单船名一样的数据有{}条", sameShipList.size());
-        // 获取符合更新条件的数据，更新港口信息
+        log.info("=================云纳船名/目的港和水果通目的港/提单船名一样的数据有{}条", sameShipList.size());
+        // 获取符合更新条件的数据，更新中转港口信息
         if (!CommonUtils.isEmpty(sameShipList) && sameShipList.size() > 0) {
 
-            // 1. 更新货代单证表船司相关字段信息
-            shipService.updateHddzInfoForShip(sameShipList);
+            // 1. 更新货代单证表船司相关字段信息(中转港、开船时间)
+            shipService.updateHddzInfoForShip(sameShipList, totalBusinessNoStrList);
+
+            // 2. 中转港信息状态反写
+            shipService.updateShipResultUpdStatus(totalBusinessNoStrList, batchNo);
         }
+
+        // 3. 更新ETA>72h信息
+        shipService.updateHddzEtaForShip(baseDataList, etaStatusList);
+
+        // 4. eta更新状态反写
+        shipService.updateShipResultEtaStatus(etaStatusList);
     }
 
     @Transactional
     @Override
-    public void updateHddzInfoForShip(List<ShipForHddzVO> baseDataList) {
+    public void updateShipResultEtaStatus(List<ShipForHddzVO> etaStatusList) {
+
+        log.info("=======================符合更新船司结果表eta_status状态的有{}条, etaStatusList:{}", etaStatusList.size(),
+                JSONObject.toJSON(etaStatusList));
+        try {
+            if (!CommonUtils.isEmpty(etaStatusList) && etaStatusList.size() > 0) {
+                // 分组保存
+                List<List<ShipForHddzVO>> splitList = CommonUtils.splitList(etaStatusList,
+                        CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
+                for (int i = 0; i < splitList.size(); i++) {
+                    ywShipPortResultMapper.updateEtaStatusAndNewEtaTimeForShip(splitList.get(i));
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, "",
+                        "更新yw_ship_port_result船司eta_status和new_eta_time反写状态-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    @Transactional
+    @Override
+    public void updateShipResultUpdStatus(List<String> ywbhList, String batchNo) {
+
+        // 业务编号去重
+        List<String> totalBusinessNoStrList = ywbhList.stream().distinct().collect(Collectors.toList());
+
+        log.info("=======================符合更新船司结果表反写状态的有{}条, ywbhList:{}", totalBusinessNoStrList.size(),
+                JSONObject.toJSON(totalBusinessNoStrList));
+        try {
+            if (!CommonUtils.isEmpty(totalBusinessNoStrList) && totalBusinessNoStrList.size() > 0) {
+                // 分组保存
+                List<List<String>> splitList = CommonUtils.splitList(totalBusinessNoStrList,
+                        CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
+                for (int i = 0; i < splitList.size(); i++) {
+                    ywShipPortResultMapper.updateUpdStatusByBusinessNoList(batchNo, splitList.get(i));
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, "",
+                        "更新yw_ship_port_result船司upd_status反写状态-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    @Transactional
+    @Override
+    public void updateHddzEtaForShip(List<ShipForHddzVO> baseDataList, List<ShipForHddzVO> etaStatusList) {
+        List<ShipForHddzVO> withEtaList = baseDataList.stream()
+                .filter(vo -> !CommonUtils.isEmpty(vo.getExpectArrivalTime())).collect(Collectors.toList());
+        log.info("=================云纳ETA有值的数据有{}条", withEtaList.size());
+
+        List<ShipForHddzVO> eta72List = baseDataList.stream().filter(vo -> vo.getHours() > 72)
+                .collect(Collectors.toList());
+        log.info("=================云纳ETA>72h的数据有{}条", eta72List.size());
+
+        /**
+         *  预计靠港时间判断
+         *  ETA减当前返回数据时间大于72小时：提单号不同的 船名目的港相同 查到的ETA则反写(以大于当天数据返回时间(crtTime)的最早ETA时间反写）：
+         *  ETA减当前返回数据时间小于等于72小时：ETA则不反写，以港口ETA为准反写
+         *  ETA时间减当前时间（精确到天）小于0：ETA 不反写
+         */
         List<ShipForHddzVO> ywbhList = new ArrayList<ShipForHddzVO>();
-        //
+
+        // 船名|目的港 分组
+        Map<String, List<ShipForHddzVO>> basicMap = withEtaList.stream()
+                .collect(Collectors.groupingBy(e -> (e.getShipName() + "|" + e.getDestinationPort())));
+        for (Map.Entry<String, List<ShipForHddzVO>> entry : basicMap.entrySet()) {
+
+            // 分组后的每一组数据都对应列表的一条数据
+            String mapKey = entry.getKey();
+            log.info("@@@@@@@@@@@@@@@@@@@@@ eta-mapKey :{} ", mapKey);
+            List<ShipForHddzVO> mapList = entry.getValue();
+            log.info("@@@@@@@@@@@@@@@@@@@@@ eta-mapList.size= {} ", mapList.size());
+
+            if (!CommonUtils.isEmpty(mapList) && mapList.size() > 0) {
+                // 过滤掉ETA < 当前时间的数据， 取最小值
+                Optional<ShipForHddzVO> min = mapList.stream()
+                        .filter(e -> DateUtils.checkStartAndEndDate(DateUtils.Date2String(e.getCrtTime()),
+                                DateUtils.Date2String(e.getExpectArrivalTime())))
+                        .min(Comparator.comparing(ShipForHddzVO::getExpectArrivalTime));
+                if (min.isPresent() && min.get().getExpectArrivalTime() != null) {
+                    ShipForHddzVO minEta = min.get();
+                    log.info("@@@@@@@@@@@@@@@@@@@@@ ywbh={}, 最小ETA= {} ", minEta.getBusinessNo(),
+                            DateUtils.Date2String(minEta.getExpectArrivalTime()));
+
+                    for (ShipForHddzVO eta72 : eta72List) {
+                        if (minEta.getShipName().equals(eta72.getShipName())
+                                && minEta.getDestinationPort().equals(eta72.getDestinationPort())) {
+
+                            // 将最小ETA放进来，根据业务编号更新ETA
+                            ShipForHddzVO ywbhVo = new ShipForHddzVO();
+                            ywbhVo.setBusinessNo(eta72.getBusinessNo());
+                            ywbhVo.setHours(eta72.getHours());
+                            ywbhVo.setExpectArrivalTime(eta72.getExpectArrivalTime());
+                            ywbhVo.setNewExpectArrivalTime(minEta.getExpectArrivalTime());
+                            ywbhVo.setBatchNo(eta72.getBatchNo());
+
+                            ywbhList.add(ywbhVo);
+                        }
+                    }
+                }
+            }
+        }
+
+        log.info("=======================符合更新yw_hddz表ETA信息的有{}条", ywbhList.size());
+        try {
+            // 根据业务编号更新ETA
+            if (!CommonUtils.isEmpty(ywbhList) && ywbhList.size() > 0) {
+                // 分组保存
+                List<List<ShipForHddzVO>> splitList = CommonUtils.splitList(ywbhList,
+                        CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
+                for (int i = 0; i < splitList.size(); i++) {
+                    shipPortMapper.updateShipEtaListForHddz(splitList.get(i));
+                }
+
+                etaStatusList.addAll(ywbhList);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, "",
+                        "反写yw_hddz船司ETA信息-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    @Transactional
+    @Override
+    public void updateHddzInfoForShip(List<ShipForHddzVO> baseDataList, List<String> ywbhStrList) {
+
+        List<ShipForHddzVO> shipList = new ArrayList<ShipForHddzVO>();
+        List<ShipForHddzVO> noTransitInfoList = baseDataList
+                .stream().filter(vo -> CommonUtils.isEmpty(vo.getTransitPort())
+                        && CommonUtils.isEmpty(vo.getTransitShipName()) && CommonUtils.isEmpty(vo.getTransitVoyage()))
+                .collect(Collectors.toList());
+        log.info("=================云纳中转港/中转船名/航次(三个字段都为空)的数据有{}条", noTransitInfoList.size());
+        List<ShipForHddzVO> withTransitInfoList = baseDataList
+                .stream().filter(vo -> !CommonUtils.isEmpty(vo.getTransitPort())
+                        && !CommonUtils.isEmpty(vo.getTransitShipName()) && !CommonUtils.isEmpty(vo.getTransitVoyage()))
+                .collect(Collectors.toList());
+        log.info("=================云纳中转港/中转船名/航次(三个字段都有值)的数据有{}条", withTransitInfoList.size());
+        shipList.addAll(noTransitInfoList);
+        shipList.addAll(withTransitInfoList);
+
+        List<ShipForHddzVO> ywbhList = new ArrayList<ShipForHddzVO>();
         // 根据提单号+业务编号分组 ztdh|ywbh
-        Map<String, List<ShipForHddzVO>> basicMap = baseDataList.stream()
+        Map<String, List<ShipForHddzVO>> basicMap = shipList.stream()
                 .collect(Collectors.groupingBy(e -> (e.getLoadingNumber() + "|" + e.getBusinessNo())));
         for (Map.Entry<String, List<ShipForHddzVO>> entry : basicMap.entrySet()) {
 
@@ -114,14 +286,28 @@
         }
 
         log.info("=======================符合更新yw_hddz表船司信息条件的有{}条", ywbhList.size());
-        // 根据业务编号更新ATA、ETA、航次、卸货港区
-        if (!CommonUtils.isEmpty(ywbhList) && ywbhList.size() > 0) {
-            // 分组保存
-            List<List<ShipForHddzVO>> splitList = CommonUtils.splitList(ywbhList,
-                    CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
-            for (int i = 0; i < splitList.size(); i++) {
-                shipPortMapper.updateShipInfoListForHddz(splitList.get(i));
+        try {
+            // 根据业务编号更新ATA、ETA、航次、卸货港区
+            if (!CommonUtils.isEmpty(ywbhList) && ywbhList.size() > 0) {
+                // 分组保存
+                List<List<ShipForHddzVO>> splitList = CommonUtils.splitList(ywbhList,
+                        CommonInfo.SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED);
+                for (int i = 0; i < splitList.size(); i++) {
+                    shipPortMapper.updateShipInfoListForHddz(splitList.get(i));
+                }
+
+                List<String> businessNoList = ywbhList.stream().filter(vo -> !CommonUtils.isEmpty(vo.getBusinessNo()))
+                        .distinct().map(vo -> vo.getBusinessNo()).collect(Collectors.toList());
+                ywbhStrList.addAll(businessNoList);
             }
+        } catch (Exception e) {
+            e.printStackTrace();
+            try {
+                fruitShipPortService.saveShipPortError(CommonInfo.ERROR_CODE_DATABASE, "",
+                        "反写yw_hddz船司信息-数据库异常：" + e.getMessage());
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
     }
 
@@ -131,29 +317,24 @@
         ywbhVo.setBusinessNo(list0.getBusinessNo());
         ywbhVo.setActualSailingTime(list0.getActualSailingTime());
         ywbhVo.setHours(list0.getHours());
-        // 云钠没有返回 中转港/中转船名/航次 数据 清空
+        // 云钠没有返回 中转港/中转船名/航次(三个字段都为空) 数据 清空
         if (CommonUtils.isEmpty(list0.getTransitPort()) && CommonUtils.isEmpty(list0.getTransitShipName())
                 && CommonUtils.isEmpty(list0.getTransitVoyage())) {
             ywbhVo.setTransitPort("");
             ywbhVo.setTransitFlag(CommonInfo.COMMON_N);
             ywbhVo.setTransitShipName("");
             ywbhVo.setTransitVoyage("");
-        } else {
-            // 云钠返回中转港/中转船名/航次 数据与水果通 船名/航次不一致或者水果通无信息 直接反写
+
+        } else if (!CommonUtils.isEmpty(list0.getTransitPort()) && !CommonUtils.isEmpty(list0.getTransitShipName())
+                && !CommonUtils.isEmpty(list0.getTransitVoyage())) {
+
+            // 云钠返回中转港/中转船名/航次(三个字段都有值)，与水果通 船名/航次不一致或者水果通无信息 直接反写
             ywbhVo.setTransitPort(list0.getTransitPort());
             ywbhVo.setTransitFlag(CommonInfo.COMMON_Y);
             ywbhVo.setTransitShipName(list0.getTransitShipName());
             ywbhVo.setTransitVoyage(list0.getTransitVoyage());
         }
 
-        /**
-         *  TODO 预计靠港时间判断
-         *  ETA减当前返回数据时间大于72小时：提单号不同的 船名目的港相同 查到的ETA则反写(以最早ETA时间反写）：
-         *  ETA减当前返回数据时间小于等于72小时：ETA则不反写，以港口ETA为准反写
-         *  ETA时间减当前时间（精确到天）小于0：ETA 不反写
-         */
-        ywbhVo.setExpectArrivalTime(list0.getExpectArrivalTime());
-
         return ywbhVo;
     }
 
Index: jinan/trunk/yunna/src/main/java/com/freshport/util/CommonInfo.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/util/CommonInfo.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/util/CommonInfo.java	(revision 33814)
@@ -50,16 +50,43 @@
     /** 查询类型-港口  10>ETA>72h*/
     public static final String TYPE_PORT_TMP = "PORT_TMP";
 
+    /** 保存日志类型 1-提单号查询船司*/
+    public static final String LOG_TYPE_LOADING_SHIP = "1";
+
+    /** 保存日志类型 2-提单号查询港口*/
+    public static final String LOG_TYPE_LOADING_PORT = "2";
+
+    /** 保存日志类型 3-回传船司结果*/
+    public static final String LOG_TYPE_RESULT_SHIP = "3";
+
+    /** 保存日志类型 4-回传港口结果*/
+    public static final String LOG_TYPE_RESULT_PORT = "4";
+
     /** 目的港：上海*/
     public static final String PORT_SH = "上海";
 
     /**操作参数个数 批量分组200条/组*/
     public static final int SQLSERVER_BATCH_GROUPING_COUNT_TWO_HUNDRED = 200;
 
-    /**操作参数个数 批量分组190条/组*/
-    public static final int SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED_190 = 190;
+    /**操作参数个数 批量分组150条/组*/
+    public static final int SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED_150 = 150;
 
     /**操作参数个数 批量分组100条/组*/
-    public static final int SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED = 200;
+    public static final int SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED = 100;
 
+    /**操作参数个数 批量分组80条/组*/
+    public static final int SQLSERVER_BATCH_GROUPING_COUNT_HUNDRED_80 = 80;
+
+    /** 异常日志，错误码 3-数据库异常 */
+    public static final String ERROR_CODE_DATABASE = "3";
+
+    /** 异常日志，错误码 4-程序异常 */
+    public static final String ERROR_CODE_PROGRAM = "4";
+
+    /** 异常日志，错误码 6-船司回传数量不对 */
+    public static final String ERROR_CODE_SHIP_NUM = "6";
+
+    /** 异常日志，错误码 6-港口回传数量不对 */
+    public static final String ERROR_CODE_PORT_NUM = "7";
+
 }
Index: jinan/trunk/yunna/src/main/java/com/freshport/util/DateUtils.java
===================================================================
--- jinan/trunk/yunna/src/main/java/com/freshport/util/DateUtils.java	(revision 33813)
+++ jinan/trunk/yunna/src/main/java/com/freshport/util/DateUtils.java	(revision 33814)
@@ -9,6 +9,7 @@
  */
 package com.freshport.util;
 
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
@@ -46,6 +47,35 @@
 
     /**
      * 
+     * getStringToDate(String日期转date, 默认格式yyyy-MM-dd HH:mm:ss)      
+     * @param date
+     * @return
+     * @throws ParseException  
+     * @return Date  
+     * @Exception 异常对象    
+     * @author lixd  
+     * @date 2023-03-28 09:59:02
+     */
+    public static Date getStringToDate(String date) {
+        try {
+            return dfm.parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static Date getStringToDate(String date, String formatter) {
+        try {
+            return new SimpleDateFormat(formatter).parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 
      * checkStartAndEndDate(这里用一句话描述这个方法的作用)       
      * @param startDate yyyy-MM-dd HH:mm:ss
      * @param endDate yyyy-MM-dd HH:mm:ss
Index: jinan/trunk/yunna/src/main/resources/application-prod.yml
===================================================================
--- jinan/trunk/yunna/src/main/resources/application-prod.yml	(revision 33813)
+++ jinan/trunk/yunna/src/main/resources/application-prod.yml	(revision 33814)
@@ -1,6 +1,6 @@
 spring:
   datasource:
-    url: jdbc:sqlserver://www.fruitease.com;DatabaseName=zjnb
+    url: jdbc:sqlserver://www.fruitease.com;DatabaseName=zjnb;allowMultiQueries=true
     username: oheng
     password: Hongshen_110
     type: com.alibaba.druid.pool.DruidDataSource
Index: jinan/trunk/yunna/src/main/resources/application-test.yml
===================================================================
--- jinan/trunk/yunna/src/main/resources/application-test.yml	(revision 33813)
+++ jinan/trunk/yunna/src/main/resources/application-test.yml	(revision 33814)
@@ -1,6 +1,6 @@
 spring:
   datasource:
-    url: jdbc:sqlserver://rm-bp107kof940zw01k6qo.sqlserver.rds.aliyuncs.com:1433;DatabaseName=zjnb_rq
+    url: jdbc:sqlserver://rm-bp107kof940zw01k6qo.sqlserver.rds.aliyuncs.com:1433;DatabaseName=zjnb_rq;allowMultiQueries=true
     username: oheng
     password: Hongshen_110
     type: com.alibaba.druid.pool.DruidDataSource
@@ -31,7 +31,7 @@
   routes:
     api:
       path: /api/**
-      url: http://localhost:9112/
+      url: http://47.97.9.10:9112/ ##http://47.97.9.10:9112/
   ratelimit:
     repository: REDIS
     enabled: true
Index: jinan/trunk/yunna/src/main/resources/generatorConfig.xml
===================================================================
--- jinan/trunk/yunna/src/main/resources/generatorConfig.xml	(revision 33813)
+++ jinan/trunk/yunna/src/main/resources/generatorConfig.xml	(revision 33814)
@@ -23,7 +23,7 @@
 		<javaClientGenerator targetPackage="com.freshport.dao"
 			targetProject="yunna" type="XMLMAPPER" />
 			
-		<table domainObjectName="YwShipPortError" tableName="yw_ship_port_error"
+		<table domainObjectName="YwShipPortLog" tableName="yw_ship_port_log"
   			enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false"
      		enableSelectByExample="false" selectByExampleQueryId="false"/>  
 		<!-- 指定生成的表 -->
