Explorar o código

订单服务callOrder

jlutt@163.com %!s(int64=2) %!d(string=hai) anos
pai
achega
434dee24f7

+ 5 - 0
conf/application-ddWebOne.xml

@@ -275,6 +275,11 @@
                 <isUseScriptService value="false"/>
             </service>
 
+            <service value="com.dderp.business.service.flycat.OrderServiceImpl" groups="DELIVER_SERVICE_REMOTE">
+                <master value="true"/>
+                <isUseScriptService value="true"/>
+            </service>
+
             <service value="com.dderp.business.service.flycat.OrderSearchServiceImpl" groups="DELIVER_SERVICE_REMOTE">
                 <master value="true"/>
                 <isUseScriptService value="true"/>

+ 12 - 0
conf/script/1000/business/BE_DocClearScriptCache.groovy

@@ -2,6 +2,7 @@ import com.dderp.common.api.BusinessExecutor
 import com.dderp.common.api.DocInfoService
 import com.dderp.common.api.SystemService
 import com.dderp.common.api.flycat.ExpressOutService
+import com.dderp.common.api.flycat.OrderSearchService
 import com.dderp.common.datas.ERPModule
 import com.dderp.common.datas.ERPModuleEntity
 import com.dderp.common.entity.base.BusinessOperation
@@ -31,6 +32,9 @@ class BE_DocClearScriptCache implements BusinessExecutor<ProcessEntityItem<ERPMo
     @Resource
     ExpressOutService expressOutService
 
+    @Resource
+    OrderSearchService orderSearchService
+
     @Override
     String scriptName() {
         return "保存业务脚本清除对象"
@@ -53,6 +57,7 @@ class BE_DocClearScriptCache implements BusinessExecutor<ProcessEntityItem<ERPMo
             systemService.reloadScriptCache(source.inputItem.code, ERPModule.SYSTEM, source.dataSourceId, source.supplierCode)
             docInfoService.reloadScriptCache(source.inputItem.code, ERPModule.SYSTEM, source.dataSourceId, source.supplierCode)
             expressOutService.reloadScriptCache(source.inputItem.code, ERPModule.SYSTEM, source.dataSourceId, source.supplierCode)
+            orderSearchService.reloadScriptCache(source.inputItem.code, ERPModule.SYSTEM, source.dataSourceId, source.supplierCode)
         }
         else {
             switch (erpModule) {
@@ -86,6 +91,13 @@ class BE_DocClearScriptCache implements BusinessExecutor<ProcessEntityItem<ERPMo
                         expressOutService.reloadScriptCache(source.getInputItem().getCode(), erpModule, source.getDataSourceId(), source.getSupplierCode())
                     }
                     break
+                case ERPModule.ERP_ORDER_SEARCH:
+                    if (source.getOperation() == BusinessOperation.SAVE) {
+                        orderSearchService.invalidateScriptCache(source.getSupplierCode() + "-" + source.getInputItem().getCode())
+                    } else {
+                        orderSearchService.reloadScriptCache(source.getInputItem().getCode(), erpModule, source.getDataSourceId(), source.getSupplierCode())
+                    }
+                    break
                 case ERPModule.ADDRESSPARSER:
                     break
                 case ERPModule.APP:

+ 77 - 51
conf/script/1000/expressApi/BE_Express_CreateOrder_SFTC.groovy

@@ -1,11 +1,15 @@
 import com.alibaba.fastjson2.JSON
 import com.dderp.common.api.BusinessExecutor
 import com.dderp.common.api.ERPLockDataService
+import com.dderp.common.api.StoreService
+import com.dderp.common.api.flycat.OrderSearchService
 import com.dderp.common.datas.ERPModule
 import com.dderp.common.datas.RedisKeys
 import com.dderp.common.entity.base.InvokeCallParams
 import com.dderp.common.entity.base.InvokeCallResult
-import com.dderp.common.entity.express.*
+import com.dderp.common.entity.order.BusinessOrder
+import com.dderp.common.entity.store.StorePlatformRequire
+import com.dderp.common.entity.store.ViewStoreInfo
 import com.dderp.common.http.HttpTools
 import com.dySweetFishPlugin.sql.dao.OperatorWait
 import com.sweetfish.convert.json.JsonConvert
@@ -43,6 +47,12 @@ class BE_Express_CreateOrder_SFTC implements BusinessExecutor<InvokeCallParams,
     @Resource
     ERPLockDataService lockDataService
 
+    @Resource
+    OrderSearchService orderSearchService
+
+    @Resource
+    StoreService storeService
+
     @Override
     String scriptName() {
         return "顺丰同城创建订单"
@@ -67,6 +77,11 @@ class BE_Express_CreateOrder_SFTC implements BusinessExecutor<InvokeCallParams,
         String orderId = invokeOrder["orderId"] as String
         //todo 获取订单信息
 
+        RetResult<BusinessOrder> orderResult = orderSearchService.getBusinessOrder(Long.parseLong(orderId), source.currentUser, source.dataSourceId, source.supplierCode)
+        if (!orderResult.isSuccess()) {
+            return RetResult.<InvokeCallParams> errorT().retinfo("无效的订单信息")
+        }
+
         return RetResult.<InvokeCallParams> successT().result(source)
     }
 
@@ -78,7 +93,6 @@ class BE_Express_CreateOrder_SFTC implements BusinessExecutor<InvokeCallParams,
 
         String orderId = invokeOrder["orderId"] as String
 
-        //todo 获取订单信息
         if (lockDataService.hLockAdd(orderId, RedisKeys.KEY_ERP_WORKING_ORDER, source.supplierCode) > 1) {
             return RetResult.<InvokeCallParams> errorT().retinfo(orderId + "提交工作中,请稍后刷新即可,无需重复操作")
         }
@@ -97,51 +111,68 @@ class BE_Express_CreateOrder_SFTC implements BusinessExecutor<InvokeCallParams,
     }
 
     RetResult<InvokeCallResult> execute(InvokeCallParams source) {
+        //检查订单信息
+        def jsonSlurper = new JsonSlurper()
+        def invokeOrder = jsonSlurper.parseText(source.params)
+
+        String orderId = invokeOrder["orderId"] as String
+
+        RetResult<BusinessOrder> orderResult = orderSearchService.getBusinessOrder(Long.parseLong(orderId), source.currentUser, source.dataSourceId, source.supplierCode)
+        if (!orderResult.isSuccess()) {
+            return RetResult.<InvokeCallResult> errorT().retinfo("无效的订单信息")
+        }
+
+        BusinessOrder businessOrder = orderResult.result
+
+        ViewStoreInfo viewStoreInfo = storeService.getViewStoreInfo(businessOrder.idStore, source.supplierCode, false, false, true)
+        if (viewStoreInfo == null) {
+            return RetResult.<InvokeCallResult> errorT().retinfo("无效的门店信息")
+        }
+        if (viewStoreInfo.storeInfo == null) {
+            return RetResult.<InvokeCallResult> errorT().retinfo("无效的门店信息")
+        }
+        StorePlatformRequire storePlatformRequire = viewStoreInfo.storeInfo.requireItem("SFTC", "shopId")
+        if (storePlatformRequire == null) {
+            return RetResult.<InvokeCallResult> errorT().retinfo("门店未设置顺丰店铺id")
+        }
+
         //秒级时间戳,groovy里面不让用system
         long currentTime = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8))
         long testTime = LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli()
-        SFOrder sfOrder = new SFOrder(
-                dev_id: sfAppId,
-                shop_id: "3243279847393",
-                shop_type: 1,
-                shop_order_id: "JY" + testTime + "L",
-                order_sequence: "测试",
-                lbs_type: 2,
-                order_time: currentTime,
-                push_time: currentTime,
-                vehicle: 0,
-                four_wheeler_type: 10,
-                rider_pick_method: 1,
-                version: 19,
-
-                order_detail: new SFOrderDetail(
-                        total_price: 30100L,
-                        product_type: 6,
-                        weight_gram: 3000L,
-                        product_num: 15,
-                        product_type_num: 5,
-                        product_detail: [
-                                new SFOrderProductDetail(
-                                        product_name: "测试商品1",
-                                        product_num: 1
-                                ),
-                                new SFOrderProductDetail(
-                                        product_name: "测试商品2",
-                                        product_num: 3
-                                ),
-                        ]
-
-                ),
-
-                receive: new SFOrderReceive(
-                        user_name: "顺丰同城",
-                        user_phone: "18237171439",
-                        user_lng: "116.339392",
-                        user_lat: "40.002349",
-                        user_address: "北京市海淀区学清嘉创大厦A座15层"
-                )
-        )
 
+        def sfOrder = [
+                dev_id        : sfAppId,
+                shop_id       : storePlatformRequire.itemValue,
+                shop_type     : 1,
+                shop_order_id : businessOrder.orderCode,
+                order_source  : businessOrder.incomePlatformName,
+                order_sequence: String.valueOf(businessOrder.orderSequence),
+                order_time    : currentTime,
+                push_time     : currentTime,
+                version       : 19,
+
+                order_detail  : [
+                        total_price     : 30100L,
+                        product_type    : 1,
+                        weight_gram     : 3000L,
+                        product_num     : 15,
+                        product_type_num: 5,
+                        product_detail  : businessOrder.detailItemList.collect { detailItem ->
+                            def productDetail = [
+                                    product_name: detailItem.itemName,
+                                    product_num : detailItem.itemCount
+                            ]
+                            return productDetail
+                        }
+                ],
+                receive       : [
+                        user_name   : businessOrder.orderDeliveryInfo.receiveMan,
+                        user_phone  : businessOrder.orderDeliveryInfo.contractPhone,
+                        user_lng    : String.valueOf(businessOrder.orderDeliveryInfo.geoPoiLocation.longitude),
+                        user_lat    : String.valueOf(businessOrder.orderDeliveryInfo.geoPoiLocation.latitude),
+                        user_address: businessOrder.orderDeliveryInfo.deliverAddress
+                ]
+        ]
 
         String postData = JSON.toJSONString(sfOrder)
         logger.info("请求数据: " + postData)
@@ -155,16 +186,11 @@ class BE_Express_CreateOrder_SFTC implements BusinessExecutor<InvokeCallParams,
                 postData,
                 ["Content-Type": "application/json;charset=utf-8"])
         try {
-            String orderResult = apiResult.get(6000, TimeUnit.SECONDS)
-
-            def jsonSlurper = new JsonSlurper()
-            def sfOrderJson = jsonSlurper.parseText(orderResult)
+            String sfCreateOrderJson = apiResult.get(6000, TimeUnit.SECONDS)
 
-            logger.info(sfOrderJson)
+            def sfOrderData = jsonSlurper.parseText(sfCreateOrderJson)
 
-            SFCreateOrderResult createOrderResult = jsonConvert.convertFromO(SFCreateOrderResult.class, orderResult)
-            logger.info(orderResult)
-            logger.info(jsonConvert.convertTo(createOrderResult))
+            logger.info(sfOrderData)
 
             return RetResult.<InvokeCallResult> successT()
         } catch (InterruptedException | ExecutionException | TimeoutException e) {

+ 109 - 0
conf/script/1000/expressApi/BE_Express_PreCreateOrder_SFTC.groovy

@@ -0,0 +1,109 @@
+import com.alibaba.fastjson2.JSON
+import com.dderp.common.api.BusinessExecutor
+import com.dderp.common.api.ERPLockDataService
+import com.dderp.common.datas.ERPModule
+import com.dderp.common.entity.base.InvokeCallParams
+import com.dderp.common.entity.base.InvokeCallResult
+import com.dderp.common.http.HttpTools
+import com.dySweetFishPlugin.sql.dao.OperatorWait
+import com.sweetfish.convert.json.JsonConvert
+import com.sweetfish.service.RetResult
+import groovy.json.JsonSlurper
+import org.apache.logging.log4j.LogManager
+import org.apache.logging.log4j.Logger
+
+import javax.annotation.Resource
+import java.nio.charset.StandardCharsets
+import java.time.LocalDateTime
+import java.time.ZoneOffset
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+
+@SuppressWarnings("unused")
+class BE_Express_PreCreateOrder_SFTC implements BusinessExecutor<InvokeCallParams, InvokeCallResult> {
+
+    private final Logger logger = LogManager.getLogger(this.getClass().getSimpleName())
+
+    @Resource(name = "property.sftc.appId")
+    long sfAppId
+
+    @Resource(name = "property.sftc.appKey")
+    String sfAppKey
+
+    @Resource(name = "property.sftc.apiUrl")
+    String sfApiUrl
+
+    @Resource
+    JsonConvert jsonConvert
+
+    @Resource
+    ERPLockDataService lockDataService
+
+    @Override
+    String scriptName() {
+        return "顺丰同城预创建订单"
+    }
+
+    @Override
+    ERPModule module() {
+        return ERPModule.EXPRESS_API
+    }
+
+    @Override
+    OperatorWait getAWait(InvokeCallParams source) {
+        return OperatorWait.SYNC
+    }
+
+    @Override
+    RetResult<InvokeCallParams> checkExecute(InvokeCallParams source) {
+        //检查订单信息
+        def jsonSlurper = new JsonSlurper()
+        def invokeOrder = jsonSlurper.parseText(source.params)
+
+        String orderId = invokeOrder["orderId"] as String
+        //todo 获取订单信息
+
+        return RetResult.<InvokeCallParams> successT().result(source)
+    }
+
+    RetResult<InvokeCallResult> execute(InvokeCallParams source) {
+        //预创建订单,并非真正发单;用来验证是否可以发单并在成功时返回时效、计价等信息,也可用来验证地址以及时间是否在顺丰的配送范围内
+        //秒级时间戳,groovy里面不让用system
+        long currentTime = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8))
+
+        def sfOrder = [
+                dev_id      : sfAppId,
+                shop_type   : 1,
+                user_address: "北京市海淀区国泰大厦",
+                push_time   : currentTime
+        ]
+
+        String postData = JSON.toJSONString(sfOrder)
+        logger.info("请求数据: " + postData)
+        String sign = ExpressApiSign.sfGenerateOpenSign(postData, sfAppId, sfAppKey)
+
+        String url = sfApiUrl + "precreateorder?sign=" + sign
+
+        CompletableFuture<String> apiResult = HttpTools.postHttpContentAsync(url,
+                5000,
+                StandardCharsets.UTF_8,
+                postData,
+                ["Content-Type": "application/json;charset=utf-8"])
+        try {
+            String orderResult = apiResult.get(6000, TimeUnit.SECONDS)
+
+            def jsonSlurper = new JsonSlurper()
+            def sfOrderJson = jsonSlurper.parseText(orderResult)
+
+            logger.info(sfOrderJson)
+
+            return RetResult.<InvokeCallResult> successT()
+        } catch (InterruptedException | ExecutionException | TimeoutException e) {
+            logger.error(e.getMessage(), e)
+
+            return RetResult.<InvokeCallResult> errorT().retinfo(e.getMessage())
+        }
+    }
+}

+ 1 - 0
ddBusiness/src/main/java/com/dderp/business/service/flycat/OrderSearchServiceImpl.java

@@ -104,6 +104,7 @@ public class OrderSearchServiceImpl extends BaseService implements OrderSearchSe
         RMap<String, Long> longRMap = idsMap.get();
         try {
             longRMap.put(ERPUtils.PARAM_SEARCH_ID, idOrder);
+            //searchBusinessOrder是同步调用的,所以可以这样try finally,如果有异步情况,则在完成里面调用,参考doId之类的实现
             return searchBusinessOrder(longRMap, currentUser, dataSourceId, supplierCode, options);
         } finally {
             idsMap.accept(longRMap);

+ 27 - 0
ddBusiness/src/main/java/com/dderp/business/service/flycat/OrderServiceImpl.java

@@ -4,14 +4,25 @@ import com.dderp.common.api.NoSqlKeysService;
 import com.dderp.common.api.flycat.OrderService;
 import com.dderp.common.base.BaseService;
 import com.dderp.common.datas.RedisKeys;
+import com.dderp.common.entity.base.InvokeCallParams;
+import com.dderp.common.entity.base.InvokeCallResult;
+import com.dderp.common.entity.site.ERPTokenUser;
 import com.dySweetFishPlugin.redis.RedisService;
+import com.sweetfish.service.Local;
+import com.sweetfish.service.RetResult;
 import com.sweetfish.util.AnyValue;
+import com.sweetfish.util.AutoLoad;
+import com.sweetfish.util.ResourceType;
+import org.apache.commons.lang3.StringUtils;
 
 import javax.annotation.Resource;
 import java.time.Duration;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 
+@AutoLoad(false)
+@Local
+@ResourceType(OrderService.class)
 public class OrderServiceImpl extends BaseService implements OrderService {
 
     @Resource
@@ -58,4 +69,20 @@ public class OrderServiceImpl extends BaseService implements OrderService {
         }
         return orderSequence;
     }
+
+    public RetResult<InvokeCallResult> callOrder(InvokeCallParams source, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
+        if (source == null) {
+            return RetResult.<InvokeCallResult>errorT().retinfo("无效的参数信息");
+        }
+
+        if (StringUtils.isEmpty(source.getBusinessMethod())) {
+            return RetResult.<InvokeCallResult>errorT().retinfo("无效的参数方法[businessMethod]信息");
+        }
+
+        source.setCurrentUser(currentUser);
+        source.setDataSourceId(dataSourceId);
+        source.setSupplierCode(supplierCode);
+
+        return callScript(source.getBusinessMethod(), source, currentUser, dataSourceId, supplierCode);
+    }
 }

+ 9 - 2
ddCommon/src/main/java/com/dderp/common/api/flycat/OrderService.java

@@ -1,15 +1,22 @@
 package com.dderp.common.api.flycat;
 
 import com.dderp.common.api.ScriptService;
+import com.dderp.common.entity.base.InvokeCallParams;
+import com.dderp.common.entity.base.InvokeCallResult;
+import com.dderp.common.entity.site.ERPTokenUser;
+import com.sweetfish.service.RetResult;
 
 public interface OrderService extends ScriptService {
 
     /**
      * 获取订单流水号
      * 每个门店每个订单平台每天的流水号,从1开始,零点归1
-     * @param idShop 门店id
-     * @param idPlatform 订单平台id
+     *
+     * @param idShop       门店id
+     * @param idPlatform   订单平台id
      * @param supplierCode 分表
      */
     long getOrderSequence(long idShop, long idPlatform, long supplierCode);
+
+    RetResult<InvokeCallResult> callOrder(InvokeCallParams source, ERPTokenUser currentUser, String dataSourceId, long supplierCode);
 }

+ 5 - 5
ddCommon/src/main/java/com/dderp/common/base/BaseService.java

@@ -632,7 +632,7 @@ public abstract class BaseService extends AbstractService {
                     }
 
                     //执行execute方法
-                    OperatorWait aWait = businessExecutor.getAWait(source);
+                    OperatorWait aWait = businessExecutor.getAWait(beforeResult.getResult());
                     if (aWait == OperatorWait.SYNC) {
                         try {
                             RetResult<InvokeCallResult> scriptResult = businessExecutor.execute(beforeResult.getResult());
@@ -924,7 +924,7 @@ public abstract class BaseService extends AbstractService {
      * @param <R>             脚本执行输出类型
      * @return 操作数据
      */
-    @SuppressWarnings({"rawtypes", "unchecked"})
+    @SuppressWarnings({"rawtypes", "unchecked", "SameParameterValue"})
     protected <S extends BaseEntity, R extends BaseEntity> RetResult<List<R>> doIds(String ids,
                                                                                     String redisKey,
                                                                                     String actionName,
@@ -1136,7 +1136,7 @@ public abstract class BaseService extends AbstractService {
      * @param <T>         对象
      * @return 对象数组
      */
-    @SuppressWarnings({"rawtypes", "DuplicatedCode"})
+    @SuppressWarnings({"rawtypes", "DuplicatedCode", "SameParameterValue"})
     protected <T> List<T> searchESList(ESClient esClient, JsonConvert jsonConvert,
                                        Class<T> clazz,
                                        RMap searchData, QueryBuilderExecutor qbe,
@@ -1385,7 +1385,7 @@ public abstract class BaseService extends AbstractService {
      * @param <T>         对象
      * @return 对象数组
      */
-    @SuppressWarnings({"rawtypes", "DuplicatedCode", "unused"})
+    @SuppressWarnings({"rawtypes", "DuplicatedCode", "unused", "SameParameterValue"})
     protected <T> List<T> searchESList(ESClient esClient, JsonConvert jsonConvert,
                                        Class<T> clazz,
                                        RMap searchData, QueryBuilderExecutor qbe,
@@ -1423,7 +1423,7 @@ public abstract class BaseService extends AbstractService {
         return resultList;
     }
 
-    @SuppressWarnings({"rawtypes", "DuplicatedCode", "unused"})
+    @SuppressWarnings({"rawtypes", "DuplicatedCode", "unused", "SameParameterValue"})
     protected <T> List<T> searchESList(ESClient esClient, JsonConvert jsonConvert,
                                        Class<T> clazz,
                                        RMap searchData, QueryBuilderExecutor qbe,

+ 6 - 1
ddWebCore/src/main/java/com/dderp/webcore/rest/AdminRest.java

@@ -3,6 +3,7 @@ package com.dderp.webcore.rest;
 import com.dderp.common.api.DocInfoService;
 import com.dderp.common.api.SystemService;
 import com.dderp.common.api.flycat.ExpressOutService;
+import com.dderp.common.api.flycat.OrderSearchService;
 import com.dderp.common.base.BaseService;
 import com.dderp.common.datas.ERPHeader;
 import com.dderp.common.datas.ERPModule;
@@ -53,6 +54,9 @@ public class AdminRest extends BaseService {
     ExpressOutService expressOutService;
 
     @Resource
+    OrderSearchService orderSearchService;
+
+    @Resource
     JsonConvert jsonConvert;
 
 
@@ -171,7 +175,8 @@ public class AdminRest extends BaseService {
                             getLoadedScriptCache(dataSourceId, Long.parseLong(supplierCode)),
                             systemService.getLoadedScriptCache(dataSourceId, Long.parseLong(supplierCode)),
                             docInfoService.getLoadedScriptCache(dataSourceId, Long.parseLong(supplierCode)),
-                            expressOutService.getLoadedScriptCache(dataSourceId, Long.parseLong(supplierCode))
+                            expressOutService.getLoadedScriptCache(dataSourceId, Long.parseLong(supplierCode)),
+                            orderSearchService.getLoadedScriptCache(dataSourceId, Long.parseLong(supplierCode))
                     ).forEach(scriptList::addAll);
 
                     //只保留一个Init_ExpandoGroovy,这里如果正常写需要拆分两个部分,去重用TreeSet操作,只保留一个Init_ExpandoGroovy,写的有些麻烦,懒得处理了,直接用暴力的写法

+ 0 - 1
ddWebCore/src/main/java/com/dderp/webcore/servlet/ExpressCallServlet.java

@@ -85,7 +85,6 @@ public class ExpressCallServlet extends HttpServlet {
 
     @HttpMapping(url = "/express/sfCall", methods = {"POST", "GET"}, comment = "回调入口")
     public void sfCall(HttpRequest request, HttpResponse response) {
-        //简单的入口,估计也没多少接口提供出去,这里多加一层方法包一下,是担心后续会修改
         logger.info(request);
 
         //验证签名,防止乱post