From 62ca858979a61bd47763b7422a5ee2555f73a676 Mon Sep 17 00:00:00 2001 From: luoweijian <1329394916@qq.com> Date: Wed, 1 Apr 2026 14:30:04 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=8E=A5=E5=8F=A3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/entity/LogisticsOrderEntity.java | 7 ++++ .../domain/service/base/ErpService.java | 2 + .../service/base/impl/ErpServiceImpl.java | 39 ++++++++++++++++-- .../handler/SfCreateOrderHandler.java | 21 +++++++++- src/main/resources/application-test.yml | 6 +-- src/main/resources/application.yml | 10 ++--- src/main/resources/favicon.ico | Bin 0 -> 4286 bytes 7 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 src/main/resources/favicon.ico diff --git a/src/main/java/com/project/logistics/domain/entity/LogisticsOrderEntity.java b/src/main/java/com/project/logistics/domain/entity/LogisticsOrderEntity.java index fb6db98..29d3a3e 100644 --- a/src/main/java/com/project/logistics/domain/entity/LogisticsOrderEntity.java +++ b/src/main/java/com/project/logistics/domain/entity/LogisticsOrderEntity.java @@ -11,6 +11,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Comment; +import java.util.Date; + @Data @EqualsAndHashCode(callSuper = true) @Entity @@ -71,4 +73,9 @@ public class LogisticsOrderEntity extends BaseEntity { @Column(name = "sf_current_state_code", length = 32) @TableField("sf_current_state_code") private String sfCurrentStateCode; + + @Comment("下单成功时间") + @Column(name = "order_time") + @TableField("order_time") + private Date orderTime; } diff --git a/src/main/java/com/project/logistics/domain/service/base/ErpService.java b/src/main/java/com/project/logistics/domain/service/base/ErpService.java index dd84863..7bd7ebb 100644 --- a/src/main/java/com/project/logistics/domain/service/base/ErpService.java +++ b/src/main/java/com/project/logistics/domain/service/base/ErpService.java @@ -10,6 +10,8 @@ public interface ErpService { JSONObject getShipmentOrderInfo(String orderNo) throws Exception; + JSONObject getSampleOrderInfoByNo(String orderNo) throws Exception; + /** * 回写运单号到 U9 */ diff --git a/src/main/java/com/project/logistics/domain/service/base/impl/ErpServiceImpl.java b/src/main/java/com/project/logistics/domain/service/base/impl/ErpServiceImpl.java index a7f348a..8e5fe35 100644 --- a/src/main/java/com/project/logistics/domain/service/base/impl/ErpServiceImpl.java +++ b/src/main/java/com/project/logistics/domain/service/base/impl/ErpServiceImpl.java @@ -58,6 +58,39 @@ public class ErpServiceImpl implements ErpService { } } + @Override + public JSONObject getSampleOrderInfoByNo(String orderNo) throws Exception { + log.info(">>> 正在通过专属 U9 管道查询单据: {}", orderNo); + String goLiveTime = sampleProperties.getGoLiveTime(); + + String sql = "SELECT TOP 1 " + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.orderNo.getFieldName() , SampleOrderInfoFieldEnum.orderNo.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.actualSendTime.getFieldName() , SampleOrderInfoFieldEnum.actualSendTime.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.salesman.getFieldName() , SampleOrderInfoFieldEnum.salesman.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.transportMethod.getFieldName() , SampleOrderInfoFieldEnum.transportMethod.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.recipientContact.getFieldName() , SampleOrderInfoFieldEnum.recipientContact.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.recipientMobile.getFieldName() , SampleOrderInfoFieldEnum.recipientMobile.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.recipientAddress.getFieldName() , SampleOrderInfoFieldEnum.recipientAddress.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.payer.getFieldName() , SampleOrderInfoFieldEnum.payer.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.waybillNo.getFieldName() , SampleOrderInfoFieldEnum.waybillNo.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.expressType.getFieldName() , SampleOrderInfoFieldEnum.expressType.name()) + + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.fee.getFieldName() , SampleOrderInfoFieldEnum.fee.name()) + + String.format(" a.%s as %s " , SampleOrderInfoFieldEnum.quantity.getFieldName() , SampleOrderInfoFieldEnum.quantity.name()) + + "FROM InvDoc_LendTrans a WITH(NOLOCK) " + + "WHERE a.Org = '1002011064787026' " + // 指定组织 ID + " AND a.Status = 0 " + // 状态为开立/待处理 + " AND a.DescFlexField_PubDescSeg19 >= ? AND a.DocNo = ?"; + try { + Map result = u9JdbcTemplate.queryForMap(sql , goLiveTime , orderNo); + JSONObject json = new JSONObject(result); + log.info(">>> [U9查询成功]: \n{}", json.toString()); + return json; + } catch (Exception e) { + log.error(">>> [U9查询失败]: {}", e.getMessage()); + throw e; + } + } + @Override public void updateWaybillToErp(String orderNo, String waybillNo, String resourceCode, String orderType) throws Exception { log.info(">>> [U9回写] 准备将运单号 {} 写入 U9 单据 {}", waybillNo, orderNo); @@ -125,7 +158,7 @@ public class ErpServiceImpl implements ErpService { String goLiveTime = sampleProperties.getGoLiveTime(); // 具体条件请根据 U9 实际字段修改 - String sql = "SELECT DISTINCT" + + String sql = "SELECT" + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.orderNo.getFieldName() , SampleOrderInfoFieldEnum.orderNo.name()) + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.actualSendTime.getFieldName() , SampleOrderInfoFieldEnum.actualSendTime.name()) + String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.salesman.getFieldName() , SampleOrderInfoFieldEnum.salesman.name()) + @@ -139,9 +172,7 @@ public class ErpServiceImpl implements ErpService { String.format(" a.%s as %s , " , SampleOrderInfoFieldEnum.fee.getFieldName() , SampleOrderInfoFieldEnum.fee.name()) + String.format(" a.%s as %s " , SampleOrderInfoFieldEnum.quantity.getFieldName() , SampleOrderInfoFieldEnum.quantity.name()) + "FROM InvDoc_LendTrans a WITH(NOLOCK) " + - "LEFT JOIN InvDoc_LendLine b WITH(NOLOCK) ON b.LendTrans = a.ID " + - "LEFT JOIN Base_Organization_Trl c WITH(NOLOCK) ON b.Org = c.ID " + - "WHERE c.ID = '1002011064787026' " + // 指定组织 ID + "WHERE a.Org = '1002011064787026' " + // 指定组织 ID " AND a.Status = 0 " + // 状态为开立/待处理 " AND a.DescFlexField_PubDescSeg19 >= ? "; diff --git a/src/main/java/com/project/logistics/domain/strategy/handler/SfCreateOrderHandler.java b/src/main/java/com/project/logistics/domain/strategy/handler/SfCreateOrderHandler.java index 05d1178..39fe209 100644 --- a/src/main/java/com/project/logistics/domain/strategy/handler/SfCreateOrderHandler.java +++ b/src/main/java/com/project/logistics/domain/strategy/handler/SfCreateOrderHandler.java @@ -12,6 +12,7 @@ import com.project.logistics.domain.enums.*; import com.project.logistics.domain.service.SfApiService; import com.project.logistics.domain.service.WebDavService; import com.project.logistics.domain.service.base.ApiRetryTaskService; +import com.project.logistics.domain.service.base.ErpService; import com.project.logistics.domain.service.base.LogisticsOrderService; import com.project.logistics.domain.strategy.ApiTaskHandler; import lombok.extern.slf4j.Slf4j; @@ -19,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import java.util.Date; import java.util.Objects; @Slf4j @@ -37,6 +39,8 @@ public class SfCreateOrderHandler implements ApiTaskHandler { @Autowired private FixedRuleProperties fixedRuleProperties; + @Autowired + private ErpService erpService; @Override public String getActionCode() { return RetryActionEnum.SF_CREATE_ORDER.getCode(); @@ -48,8 +52,22 @@ public class SfCreateOrderHandler implements ApiTaskHandler { log.info(">>> 开始执行顺丰正式下单,单号: {}", order.getOrderNo()); // 1. 从 order_info 快照中解析出 U9 的原始数据 - JSONObject u9Data = JSON.parseObject(order.getOrderInfo()); + JSONObject u9Data; + boolean isShipment = OrderTypeEnum.SHIPMENT.getCode().equals(order.getOrderType()); + + if (isShipment) { + u9Data = JSON.parseObject(erpService.getShipmentOrderInfo(order.getOrderNo()).toString()); + } else { + // 需要在 ErpService 实现一个根据单号获取单个样品单详情的方法 + u9Data = JSON.parseObject(erpService.getSampleOrderInfoByNo(order.getOrderNo()).toString()); + } + + if (u9Data == null || u9Data.isEmpty()) { + throw new RuntimeException("实时获取 ERP 数据失败,单号可能在 U9 中已被删除"); + } + // 同步更新本地快照字段,确保数据一致 + order.setOrderInfo(u9Data.toJSONString()); // 2. 构造顺丰下单报文 (参考 PDF 第 2-10 页) JSONObject msgData = new JSONObject(); msgData.put("language", "zh-CN"); @@ -165,6 +183,7 @@ public class SfCreateOrderHandler implements ApiTaskHandler { // 5. 更新主表状态 order.setSfWaybillNo(waybillNo); + order.setOrderTime(new Date()); order.setOrderStatus(OrderStatusEnum.ORDER_SUBMITTED.getCode()); logisticsOrderService.updateById(order); diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index 3254eb7..3aa1aeb 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -73,14 +73,14 @@ logistics: windows: # 这个窗口设置10分钟有效期,配合10分钟一次的唤醒,只会跑一次 - name: "上午11点班次" - startTime: "11:00" - endTime: "11:10" + startTime: "11:08" + endTime: "11:08" intervalMinutes: 60 # 这个窗口在15-20点之间,每隔20分钟会真正跑一次逻辑 - name: "下午至傍晚波次" startTime: "15:00" endTime: "20:00" - intervalMinutes: 20 + intervalMinutes: 60 sample-scanner: enabled: true # 每 10 分钟唤醒一次 (系统开销微乎其微) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index adfb414..a8f8208 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -73,14 +73,14 @@ logistics: windows: # 这个窗口设置10分钟有效期,配合10分钟一次的唤醒,只会跑一次 - name: "上午11点班次" - startTime: "11:00" - endTime: "11:10" + startTime: "11:08" + endTime: "11:08" intervalMinutes: 60 # 这个窗口在15-20点之间,每隔20分钟会真正跑一次逻辑 - name: "下午至傍晚波次" - startTime: "15:00" - endTime: "20:00" - intervalMinutes: 20 + startTime: "15:08" + endTime: "20:08" + intervalMinutes: 60 sample-scanner: enabled: true # 每 10 分钟唤醒一次 (系统开销微乎其微) diff --git a/src/main/resources/favicon.ico b/src/main/resources/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f93c5de6598e35c263fb5195d4cc4c6d038a60d5 GIT binary patch literal 4286 zcmcgv3s98T8C^qDONUOJ#gV(i%QI*0$?|8dW` z=X=~=fnX8+Td_jG{t8Yl5eSwE1cJ8+bV=|#0=v$Ji0-}MSVZre5q?N`mGBC|bgU4j5sERT$KG=s#=TeXt>Dm3U)!R1o%nE`z;dwQfSzB8# z-?L{=w5zM@xTmKljzu5k+OO32m<0A6^R0oEt5fYsS&Ei1~e$^QGc-xb+rnv zLm{u?I+(_uo*wSM<=S_#des_Oz5hOhyS8Jahdmbm=RMd&_(6Q{Ht|nl?YIGlbz_*6 zMq+kK58Xg7l$nQ-7v)p4eA(-pjr^4r6=-X1#pRY3v^1;Gq`HJg(xI%sNIGh{jvDfV z@ps?4#rbz^-;UM4S%Y^h--VUcdN}=M8`e47Vn>JvhGV@k5-;SrIFS~@{ckPJqC60x zG9l<*s_0+I)*IeiXXIDb*W*fO2Rho@NXKQaqq(_>bTpC&%bg&V}2@zDHr=%6u6KT4Oyu3RFcrK+TpX0yovMogp~wVkKF%G z;=XzF2Gr^+k9D+OCNEl=(cGlsacOK&F5nOJ7vf-W5JE#j;IMl)wrt)4>rbpQ#T`}+DYtkt5YyBpW8UFAADJIIeV z^20=jssDjO;tvW!c&HdhBaa~bP$=wn?!=#MY+!HqC7c}WDW8QXquOEbnecBVTGkg? z4RHRucd1tOlpi`B*m>9W>$rB6bX@5~XJ>Sh3G0I&6Ik4TLE!aAbB+!S3}9+%3I>DWu@23E2EDz#=<4d? zIQO`2XxK{ zK$GKXJ3Y_^JJe=GC&fV`5@ZPj$%pOE={qgF>O;yhd)86IZXQ zd0$Q-zf%$ucwf%UIDx>x0K`gSkVXFIP%kSgAb#rECj3uvlOC3TZxVVL$CD5R1|lsj zjq0!k%!mH|J7}cdcv6~yblM*h;$smV6-n_B_Nq9DLk{9pmK24wXO*32>*x9R zka2z2@D~adDanao`)pED5*n!1dwY6uk7{9Xa1dJUFt5$}x>^*R%fVUM=|>vUm<9== zBO?(>`H(F;gR+tm9HBT#VveDtxQNGq);0QF-0V8#maMoiAGv2`2o;MV^z-BI){_6S zGpBe?GtPp%T(IZz^O%M+T*L9yWUhhL0ILP&$D`ahi$l~CPNb(ZU!Tbz92{ivO?;g6 z)Jf@dwDS(MQN6RAW9yJtS8*QZIn$6ouff!Z<2)AR1Jgj9ECv_rYRIcRV@z|NwSMD0 z(rFRrX2biy@bEAs5()P0+lQ>IES^t~G@RivU_KN)_964ze4t)bR9Jw^&CT3PnsbJ* z#>nw~$7F9i%+1Z|FhAsSIlQQs1W~UmDK17f#bbdFq#=jr1NEKsG*neq;O31koXyTQ zu08boI8E|OSPyS6;fZP zxe*=~#_Kg9A;B1HcHKY_5}y3VG*UeCSQ_iQsXX4lqq|w5V*YEpJ1}@%h5I*Kxt7^! z14<>nj3