Bläddra i källkod

Merge remote-tracking branch 'origin/main' into main

# Conflicts:
#	ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/impl/OtcTradeOrderServiceImpl.java
luofeiyun 1 vecka sedan
förälder
incheckning
cb2a295f27

+ 2 - 2
ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/api/insurance/InsuranceApi.java

@@ -19,12 +19,12 @@ public interface InsuranceApi {
 
     @Operation(summary = "申请投保")
     @PermitAll
-    CommonResult<Boolean> applyInsurance(InsuranceApplyReqDTO reqDTO);
+    CommonResult<Boolean> applyInsurance(Long orderId);
 
 
     @Operation(summary = "通过订单号退保")
     @PermitAll
-    CommonResult<Boolean> cancelInsurance(List<Long> orderIdList);
+    CommonResult<Boolean> cancelInsurance(Long orderId);
 
 
 }

+ 5 - 11
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/api/insurance/InsuranceApiImpl.java

@@ -1,14 +1,11 @@
 package com.yc.ship.module.trade.api.insurance;
 
 import com.yc.ship.framework.common.pojo.CommonResult;
-import com.yc.ship.module.trade.api.insurance.dto.InsuranceApplyReqDTO;
-import com.yc.ship.module.trade.api.insurance.dto.InsuredRespDTO;
 import com.yc.ship.module.trade.service.insurance.InsuranceService;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
-import java.util.List;
 
 /**
  */
@@ -20,16 +17,13 @@ public class InsuranceApiImpl implements InsuranceApi {
     private InsuranceService insuranceService;
 
     @Override
-    public CommonResult<Boolean> applyInsurance(InsuranceApplyReqDTO reqDTO) {
-        boolean res = insuranceService.applyInsurance(reqDTO.getOrderId());
-        return CommonResult.success(res);
+    public CommonResult<Boolean> applyInsurance(Long orderId) {
+        return CommonResult.success(insuranceService.applyInsurance(orderId));
     }
 
     @Override
-    public CommonResult<Boolean> cancelInsurance(List<Long> ticketIdList) {
-        // TODO: 待实现
-//        insuranceService.applyCancelInsurance(ticketIdList);
-//        return CommonResult.success(true);
-        return null;
+    public CommonResult<Boolean> cancelInsurance(Long orderId) {
+        insuranceService.applyCancelInsurance(orderId);
+        return CommonResult.success(true);
     }
 }

+ 5 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/dataobject/orderpolicy/OrderPolicyDO.java

@@ -2,6 +2,7 @@ package com.yc.ship.module.trade.dal.dataobject.orderpolicy;
 
 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.yc.ship.framework.tenant.core.db.TenantBaseDO;
+import com.yc.ship.module.trade.framework.annotation.ForUpdate;
 import lombok.*;
 import java.util.*;
 import java.math.BigDecimal;
@@ -43,6 +44,7 @@ public class OrderPolicyDO extends TenantBaseDO {
     /**
      * 政策ID
      */
+    @ForUpdate(fieldName = "政策ID")
     private Long policyId;
 
     /**
@@ -52,14 +54,17 @@ public class OrderPolicyDO extends TenantBaseDO {
     /**
      * 预占数量
      */
+    @ForUpdate(fieldName = "预占数量")
     private BigDecimal preUseNum;
     /**
      * 实占数量
      */
+    @ForUpdate(fieldName = "实占数量")
     private BigDecimal realUseNum;
     /**
      * 优惠金额
      */
+    @ForUpdate(fieldName = "优惠金额")
     private BigDecimal amount;
 
     /**

+ 5 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/mysql/order/TradeOrderMapper.java

@@ -196,6 +196,11 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
      */
     Map<String, Object> selectTouristExportBase(@Param("vo") TradeOrderPageReqVO reqVO);
 
+    /**
+     * 查询游客名单导出表头信息
+     */
+    Map<String, Object> selectTouristExportHead(@Param("vo") TradeOrderPageReqVO reqVO);
+
     /**
      * 小程序订单分页
      * @param iPage

+ 2 - 8
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/framework/mq/TradeMqReceiver.java

@@ -372,14 +372,12 @@ public class TradeMqReceiver {
     @RabbitListener(queues = TradeMqConfig.DL_QUEUE_INSURANCE_QUERY, concurrency = "2")
     @TenantIgnore
     public void processInsuranceQuery(String data) {
-        log.info("收到保险查询结果消息 :" + data);
-
+        log.error("收到保险查询结果消息 :" + data);
         try {
             CommonResult commonResult = insuranceUtil.queryInsurance(data);
             if (!commonResult.isSuccess()) {
                 log.error("保险查询结果消息通知出现错误{}", commonResult.getMsg());
                 tradePublishUtils.publishInsuranceQueryMsg(data, 1000*60);
-                return;
             } else {
                 String checkedData = (String) commonResult.getCheckedData();
                 JSONObject jsonObject = JSONObject.parseObject(checkedData);
@@ -396,22 +394,18 @@ public class TradeMqReceiver {
                 if("PROCESSING".equals(status)) {
                     log.error("保险查询结果,投保中,继续查询");
                     tradePublishUtils.publishInsuranceQueryMsg(data, 1000 * 60);
-                    return;
                 } else if("FAIL".equals(status)) {
                     log.error("保险查询结果,投保失败,不再查询");
-                    return;
                 } else if("SUCCESS".equals(status)) {
                     log.error("保险查询结果,投保成功,不再查询");
                     Long externalPolicyNumber = policy.getLong("externalPolicyNumber");
                     String policyNo = policy.getString("policyNo");
                     insuranceService.handleInsuranceQuery(paiedAmount, policyNo, externalPolicyNumber, status);
-                    return;
                 }
-
             }
 
         } catch (Exception e) {
-            log.error("保险查询结果消息MQ通知出现错误{}", e.getMessage());
+            log.error("保险查询结果消息MQ通知出现错误", e);
         }
 
     }

+ 6 - 65
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/handler/InsuranceHandler.java

@@ -1,18 +1,10 @@
 package com.yc.ship.module.trade.service.order.handler;
 
 
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.StrUtil;
-import com.yc.ship.framework.common.util.collection.CollectionUtils;
-import com.yc.ship.framework.common.util.object.ObjectUtils;
 import com.yc.ship.module.trade.api.insurance.InsuranceApi;
-import com.yc.ship.module.trade.api.insurance.dto.InsuranceApplyReqDTO;
 import com.yc.ship.module.trade.api.insurance.dto.InsuredDTO;
-import com.yc.ship.module.trade.api.insurance.dto.InsuredRespDTO;
 import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderDO;
 import com.yc.ship.module.trade.dal.dataobject.refund.RefundDO;
-import com.yc.ship.module.trade.enums.InsuranceStatusEnum;
 import com.yc.ship.module.trade.service.order.TradeOrderRepositoryService;
 import com.yc.ship.module.trade.service.order.bo.TradeVisitorBO;
 import com.yc.ship.module.trade.service.refund.TradeRefundRepositoryService;
@@ -21,10 +13,8 @@ import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 
 /**
@@ -48,52 +38,17 @@ public class InsuranceHandler implements TradeOrderHandler{
     @Override
     public void afterProcessSuccess(TradeOrderDO tradeOrderDO) {
         try {
+            log.error("开始处理出票成功投保业务"+tradeOrderDO.getId());
             insure(tradeOrderDO);
         }catch (Exception e){
             log.error("投保异常",e);
         }
     }
     private void insure(TradeOrderDO tradeOrderDO){
-        //获取订单中的投保产品
-        List<Map<String, Object>> insuranceProductList = tradeOrderRepositoryService.getInsuranceProductFromOrder(tradeOrderDO.getId());
-        if(CollUtil.isEmpty(insuranceProductList)){
-            return;
-        }
-
-        List<InsuranceApplyReqDTO> dataList = new ArrayList<>();
-        for (Map<String, Object> insuranceProduct : insuranceProductList) {
-            if(StrUtil.isBlank(MapUtil.getStr(insuranceProduct,"insurance_code"))){
-                continue;
-            }
-            //查询订单是否需要投保,根据订单下的游客信息是否有投保标志
-            List<TradeVisitorBO> visitorDOList = tradeOrderRepositoryService.getInsureVisitor(tradeOrderDO.getId(),MapUtil.getLong(insuranceProduct,"product_id"));
-            if(CollUtil.isEmpty(visitorDOList)){
-                log.info("当前产品无投保信息{}",MapUtil.getLong(insuranceProduct,"product_id"));
-                continue;
-            }
-            TradeVisitorBO holder = visitorDOList.get(0);
-            InsuranceApplyReqDTO reqDTO = new InsuranceApplyReqDTO();
-            reqDTO.setOrderId(tradeOrderDO.getId());
-//            reqDTO.setAmount(MapUtil.get(insuranceProduct,"insurance_amount", BigDecimal.class));
-//            reqDTO.setPremium(MapUtil.get(insuranceProduct,"num", BigDecimal.class));
-//            reqDTO.setRationType(MapUtil.get(insuranceProduct,"insurance_code", String.class));
-//            reqDTO.setTravelDate(holder.getUseDate());
-//            reqDTO.setHolderName(holder.getName());
-//            reqDTO.setHolderNo(holder.getCredentialNo());
-//            reqDTO.setInsuredList(CollectionUtils.convertList(visitorDOList, this::convert));
-            dataList.add(reqDTO);
-        }
-
-        int insureFlag = 1;
-        for (InsuranceApplyReqDTO reqDTO : dataList) {
-            log.error("投保参数{}",reqDTO);
-            boolean res = insuranceApi.applyInsurance(reqDTO).getCheckedData();
-            log.error("投保请求返回{}",res);
-            if(!res){
-                insureFlag = 0;
-            }
-        }
-        tradeOrderRepositoryService.updateOrderInsureStatus(tradeOrderDO.getId(),insureFlag);
+        log.error("投保参数{}",tradeOrderDO.getId());
+        boolean res = insuranceApi.applyInsurance(tradeOrderDO.getId()).getCheckedData();
+        log.error("投保请求返回{}",res);
+        tradeOrderRepositoryService.updateOrderInsureStatus(tradeOrderDO.getId(),res?1:0);
     }
     @Override
     public void afterRefundOrder(Long refundId) {
@@ -103,23 +58,9 @@ public class InsuranceHandler implements TradeOrderHandler{
             if(tradeOrderDO.getIsInsure() == null){
                 return;
             }
-            //先取消
-            List<Long> orderIdList = new ArrayList<>();
-            orderIdList.add(tradeOrderDO.getId());
-            insuranceApi.cancelInsurance(orderIdList);
-            //再重新投保
-            insure(tradeOrderDO);
+            insuranceApi.cancelInsurance(tradeOrderDO.getId());
         }catch (Exception e){
             log.error("再投保异常",e);
         }
     }
-
-    private InsuredDTO convert(TradeVisitorBO tradeVisitorBO){
-        InsuredDTO insuredDTO = new InsuredDTO();
-//        insuredDTO.setInsuredIdNo(tradeVisitorBO.getCredentialNo());
-        insuredDTO.setInsuredName(tradeVisitorBO.getName());
-//        insuredDTO.setInsuredIdType(String.valueOf(tradeVisitorBO.getCredentialType()));
-        return insuredDTO;
-    }
-
 }

+ 44 - 38
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/impl/OtcTradeOrderServiceImpl.java

@@ -2108,10 +2108,51 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             BigDecimal leaderAmount = summary.getLeaderAmount();
             BigDecimal withAmount = summary.getWithAmount();
             BigDecimal otherMoney = summary.getOtherMoney();
+
+            // 创建订单优惠政策数据
+            //1.先删除原来的
+            List<OrderPolicyDO> orderPolicyList = orderPolicyMapper.selectList(OrderPolicyDO::getOrderId, orderId);
+            boolean isAudit = true;
+            orderPolicyMapper.deleteByOrderId(orderId);
+            List<OrderPolicyDO> orderPolicyDOList = new ArrayList<>();
+            List<TradeOrderPolicyReqVO> policyList = createVO.getPolicyList();
+            if (policyList != null) {
+                policyList.forEach(policy -> {
+                    OrderPolicyDO orderPolicyDO = new OrderPolicyDO();
+                    orderPolicyDO.setOrderId(orderId);
+                    orderPolicyDO.setOrderNo(orderNo);
+                    orderPolicyDO.setPolicyId(policy.getPolicyId());
+                    if (Objects.equals(tradeOrderDO.getOrderStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) {
+                        orderPolicyDO.setRealUseNum(policy.getUseNum());
+                        orderPolicyDO.setPreUseNum(BigDecimal.ZERO);
+                        policyApi.updatePolicySurplusNum(policy.getPolicyId(), createVO.getVoyageId(), policy.getUseNum());
+                        //TODO: 需要修改订单金额,参考文档
+                    } else {
+                        orderPolicyDO.setRealUseNum(BigDecimal.ZERO);
+                        orderPolicyDO.setPreUseNum(policy.getUseNum());
+                    }
+                    orderPolicyDO.setAmount(policy.getAmount());
+                    orderPolicyDO.setRooms(policy.getRooms());
+                    orderPolicyDOList.add(orderPolicyDO);
+                });
+                if (!orderPolicyDOList.isEmpty()) {
+                    //TODO: 判断优惠政策是否需要审核
+                    String changedFields11 = com.yc.ship.module.trade.utils.BeanUtils.getChangedFields(orderPolicyList, orderPolicyDOList);
+                    if(StringUtils.isEmpty(changedFields11)){
+                        isAudit = false;
+                    }
+                    orderPolicyMapper.insertBatch(orderPolicyDOList);
+                }
+            }
+            tradeOrderRoomModelMapper.deleteByOrderId(orderId);
+            if (!list.isEmpty()) {
+                tradeOrderRoomModelMapper.insertBatch(list);
+            }
+
             if (!Objects.equals(shipTradeOrderCreateReqVO.getRemark(), tradeOrderDO.getRemark()) || !Objects.equals(shipTradeOrderCreateReqVO.getLinkMobile(), tradeOrderDO.getLinkMobile()) || !Objects.equals(shipTradeOrderCreateReqVO.getLinkMan(), tradeOrderDO.getLinkMan())) {
                 auditType = 2;
             }
-            if (!CollUtil.isEmpty(createVO.getPolicyList())) {
+            if (!CollUtil.isEmpty(createVO.getPolicyList()) &&isAudit) {
                 auditType = 2;
             }
             if (!Objects.equals(shipTradeOrderCreateReqVO.getAmount(), tradeOrderDO.getAmount()) && loginUser.getDistributorId() == null) {
@@ -2181,44 +2222,9 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             }
 
 
-            tradeOrderRoomModelMapper.deleteByOrderId(orderId);
-            if (!list.isEmpty()) {
-                tradeOrderRoomModelMapper.insertBatch(list);
-            }
 
-            // 创建订单优惠政策数据
-            //1.先删除原来的
-            orderPolicyMapper.deleteByOrderId(orderId);
-            List<OrderPolicyDO> orderPolicyDOList = new ArrayList<>();
-            List<TradeOrderPolicyReqVO> policyList = createVO.getPolicyList();
-            if (policyList != null) {
-                policyList.forEach(policy -> {
-                    OrderPolicyDO orderPolicyDO = new OrderPolicyDO();
-                    orderPolicyDO.setOrderId(orderId);
-                    orderPolicyDO.setOrderNo(orderNo);
-                    orderPolicyDO.setPolicyId(policy.getPolicyId());
-                    orderPolicyDO.setPolicyName(policy.getPolicyName());
-                    orderPolicyDO.setDiscount(policy.getDiscount());
-                    orderPolicyDO.setDiscountType(policy.getDiscountType());
-                    orderPolicyDO.setUseNum(policy.getUseNum());
-                    if (Objects.equals(tradeOrderDO.getOrderStatus(), TradeOrderStatusEnum.UNPAID.getStatus()) || Objects.equals(tradeOrderDO.getOrderStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) {
-                        orderPolicyDO.setRealUseNum(policy.getUseNum());
-                        orderPolicyDO.setPreUseNum(BigDecimal.ZERO);
-                        policyApi.updatePolicySurplusNum(policy.getPolicyId(), createVO.getVoyageId(), policy.getUseNum());
-                        //TODO: 需要修改订单金额,参考文档
-                    } else {
-                        orderPolicyDO.setRealUseNum(BigDecimal.ZERO);
-                        orderPolicyDO.setPreUseNum(policy.getUseNum());
-                    }
-                    orderPolicyDO.setAmount(policy.getAmount());
-                    orderPolicyDO.setRooms(policy.getRooms());
-                    orderPolicyDOList.add(orderPolicyDO);
-                });
-                if (!orderPolicyDOList.isEmpty()) {
-                    //TODO: 判断优惠政策是否需要审核
-                    orderPolicyMapper.insertBatch(orderPolicyDOList);
-                }
-            }
+
+
             //支付倒计时--不超时,有预订单
             Map<String, Object> append = TradeOrderLogUtils.append("result", "订单修改成功");
             append.put("content", content);

+ 24 - 39
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/utils/InsuranceUtil.java

@@ -6,7 +6,6 @@ import com.yc.ship.framework.common.pojo.CommonResult;
 import com.yc.ship.framework.common.util.http.HttpUtils;
 import com.yc.ship.module.trade.api.insurance.dto.InsuranceApplyReqDTO;
 import com.yc.ship.module.trade.api.insurance.dto.InsuranceCancelReqDTO;
-import com.yc.ship.module.trade.framework.mq.TradePublishUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.*;
 import org.springframework.stereotype.Component;
@@ -14,8 +13,8 @@ import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 
-import javax.annotation.Resource;
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -43,7 +42,9 @@ public class InsuranceUtil {
 
     private final Integer VALIDATE_LEVEL = 0; //校验级别,其值有 0/1
 
-    /** REST模板 */
+    /**
+     * REST模板
+     */
     private RestTemplate restTemplate;
 
     /**
@@ -57,6 +58,7 @@ public class InsuranceUtil {
     /**
      * 发送投保请求
      * 将投保请求发送到阳光系统
+     *
      * @param request 投保请求
      * @return 投保响应
      */
@@ -105,9 +107,9 @@ public class InsuranceUtil {
 
             if (response.getStatusCode() == HttpStatus.OK) {
                 String status = responseBodyJson.getString("status");
-                if("FAIL".equals(status)) {
+                if ("FAIL".equals(status)) {
                     return CommonResult.error(500, "阳光系统投保返回错误: " + response.getStatusCode() + responseBody);
-                }else {
+                } else {
                     return CommonResult.success(responseBody);
                 }
             } else {
@@ -116,19 +118,20 @@ public class InsuranceUtil {
 
         } catch (Exception e) {
             log.error("发送投保请求失败", e);
-            return CommonResult.error(500,"发送投保请求失败: " + e.getMessage());
+            return CommonResult.error(500, "发送投保请求失败: " + e.getMessage());
         }
     }
 
     /**
      * 校验保险请求
      * 在调用投保接口前,为了提高投保成功率,可先调用校验接口,检查客户系统组织的请求是否符合预期
+     *
      * @param request 投保请求
      * @return 校验响应
      */
     public CommonResult validateInsuranceRequest(InsuranceApplyReqDTO request) {
         try {
-            String reqJson =  JSONObject.toJSONString(request);
+            String reqJson = JSONObject.toJSONString(request);
 
             // 构建校验请求参数
             MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
@@ -186,13 +189,14 @@ public class InsuranceUtil {
             }
         } catch (Exception e) {
             log.error("发送校验请求失败", e);
-            throw exception0(500,"发送校验请求失败: " + e.getMessage(), e);
+            throw exception0(500, "发送校验请求失败: " + e.getMessage(), e);
         }
     }
 
     /**
      * 发送退保请求
      * 将退保请求发送到阳光系统
+     *
      * @param request 退保请求
      * @return 退保响应
      */
@@ -205,15 +209,11 @@ public class InsuranceUtil {
             params.add("appId", APPID);
             params.add("req", reqJson);
             params.add("sign", sign);
-
             HttpHeaders headers = new HttpHeaders();
             headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
-
             HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
-
-            log.info("发送退保请求到阳光系统: {}", HOST + RECEIVE_URL);
-            log.info("请求参数: appId={}, req={}, sign={}", APPID, reqJson, sign);
-
+            log.error("发送退保请求到阳光系统: {}", HOST + RECEIVE_URL);
+            log.error("请求参数: appId={}, req={}, sign={}", APPID, reqJson, sign);
             // 发送请求并获取响应
             ResponseEntity<byte[]> response = restTemplate.exchange(
                     HOST + RECEIVE_URL,
@@ -221,29 +221,20 @@ public class InsuranceUtil {
                     entity,
                     byte[].class
             );
-
-            log.info("阳光系统响应状态码: {}", response.getStatusCode());
-
+            log.error("阳光系统响应状态码: {}", response.getStatusCode());
             // 手动处理响应字节流,确保使用UTF-8编码
             byte[] responseBytes = response.getBody();
             String responseBody = null;
             if (responseBytes != null) {
-                try {
-                    responseBody = new String(responseBytes, "UTF-8");
-                } catch (UnsupportedEncodingException e) {
-                    log.error("解析响应内容编码失败", e);
-                    responseBody = new String(responseBytes);
-                }
+                responseBody = new String(responseBytes, StandardCharsets.UTF_8);
             }
-
-            log.info("阳光系统响应内容: {}", responseBody);
+            log.error("阳光系统响应内容: {}", responseBody);
             JSONObject responseBodyJson = JSONObject.parseObject(responseBody);
-
             if (response.getStatusCode() == HttpStatus.OK) {
                 String status = responseBodyJson.getString("status");
-                if("FAIL".equals(status)) {
+                if ("FAIL".equals(status)) {
                     return CommonResult.error(500, "阳光系统退保返回错误: " + response.getStatusCode() + responseBody);
-                }else {
+                } else {
                     return CommonResult.success(responseBody);
                 }
             } else {
@@ -252,7 +243,7 @@ public class InsuranceUtil {
 
         } catch (Exception e) {
             log.error("发送退保请求失败", e);
-            return CommonResult.error(500,"发送退保请求失败: " + e.getMessage());
+            return CommonResult.error(500, "发送退保请求失败: " + e.getMessage());
         }
     }
 
@@ -262,26 +253,20 @@ public class InsuranceUtil {
             request.put("appId", APPID);
             request.put("externalOrderNo", orderNo);
             request.put("key", KEY);
-            String sign = MD5Util.md5(APPID+orderNo+KEY);
+            String sign = MD5Util.md5(APPID + orderNo + KEY);
 
             MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
             params.add("appId", APPID);
             params.add("externalOrderNo", orderNo);
             params.add("sign", sign);
-
-
             String url = HOST + QUERY_URL + "?appId=" + APPID + "&externalOrderNo=" + orderNo + "&sign=" + sign;
-
-
-            log.info("发送查询请求到阳光系统: {}", url);
-
+            log.error("发送查询请求到阳光系统: {}", url);
             String s = HttpUtils.get(url, null);
-
-            log.info("阳光系统查询响应内容: {}", s);
+            log.error("阳光系统查询响应内容: {}", s);
             return CommonResult.success(s);
         } catch (Exception e) {
             log.error("发送查询请求失败", e);
-            return CommonResult.error(500,"发送查询请求失败: " + e.getMessage());
+            return CommonResult.error(500, "发送查询请求失败: " + e.getMessage());
         }
     }
 }

+ 239 - 0
ship-module-trade/ship-module-trade-biz/src/main/resources/mapper/order/TradeOrderMapper.xml

@@ -189,6 +189,245 @@
         SELECT id,parent_id parentId,cate_name cateName,sort_num sortNum from product_category WHERE type = 1 AND use_status = 1 AND deleted = 0
     </select>
 
+    <select id="selectTouristExportHead"
+            resultType="java.util.Map">
+        SELECT
+            SUM(a.num) AS totalOrders,
+            SUM(a.num1) AS adultNum,
+            SUM(a.num2) AS childBabyNum,
+            SUM(a.num3) AS withNum,
+            SUM(a.num4) AS leaderNum,
+            SUM(a.payAmount) AS totalPayAmount,
+            SUM(a.actual_amount) AS totalActualAmount,
+            IFNULL((
+                SELECT GROUP_CONCAT(CONCAT( nationalityName, '(', num, ')') SEPARATOR ' ')
+                FROM (
+                SELECT
+                IFNULL(NULLIF(tv.nationality, ''), 1) AS nationalityCode,
+                IFNULL(NULLIF(ar.name, ''), '中国') AS nationalityName,
+                COUNT(1) AS num
+                FROM trade_order td
+                INNER JOIN trade_order_user tou ON td.id = tou.order_id AND tou.deleted = 0
+                LEFT JOIN trade_detail tdl ON td.id = tdl.order_id AND tdl.deleted = 0
+                LEFT JOIN trade_visitor tv ON tdl.id = tv.detail_id AND tv.deleted = 0
+                LEFT JOIN area ar ON tv.nationality = ar.id
+                WHERE td.deleted = 0
+                    AND tou.deleted = 0
+                    AND tv.type IS NOT NULL
+                    <include refid="commonWhereConditions"/>
+                    GROUP BY nationalityCode
+                ) nationality_stats
+            ), '') AS nationalityStats,
+            IFNULL((
+                SELECT GROUP_CONCAT(CONCAT(roomName, '(', roomNum, ')') SEPARATOR ',')
+                FROM (
+                SELECT
+                CONCAT(rrm.name, tm.floor, 'F') AS roomName,
+                tm.floor AS floor,
+                COUNT(DISTINCT tm.room_index_id) AS roomNum
+                FROM trade_order td
+                INNER JOIN trade_order_user tou ON td.id = tou.order_id AND tou.deleted = 0
+                LEFT JOIN trade_detail tdl ON td.id = tdl.order_id AND tdl.deleted = 0
+                LEFT JOIN trade_visitor tv ON tdl.id = tv.detail_id AND tv.deleted = 0
+                LEFT JOIN trade_order_room_model tm ON tv.room_index_id = tm.room_index_id AND tm.deleted = 0 AND td.id = tm.order_id
+                LEFT JOIN resource_room_model rrm ON tm.room_model_id = rrm.id
+                WHERE td.deleted = 0
+                    AND tou.deleted = 0
+                    AND tv.type IS NOT NULL
+                <include refid="commonWhereConditions"/>
+                GROUP BY rrm.name, tm.floor
+                ORDER BY tm.floor
+            ) room_stats
+            ), '') AS roomStats
+        FROM (
+            SELECT
+            COUNT(1) AS num,
+            SUM(CASE WHEN tv.type IN ('adultPlus', 'adultTake') THEN 1 ELSE 0 END) AS num1,
+            SUM(CASE WHEN tv.type IN ('babyTake','babyPlus','babyNonTake','childTake','childPlus','childNonTake') THEN 1 ELSE 0 END) AS num2,
+            SUM(CASE WHEN tv.type = 'with' THEN 1 ELSE 0 END) AS num3,
+            SUM(CASE WHEN tv.type = 'leader' THEN 1 ELSE 0 END) AS num4,
+            td.pay_amount AS payAmount,
+            IFNULL(topay.actual_amount, 0) AS actual_amount
+            FROM trade_order td
+            INNER JOIN trade_order_user tou ON td.id = tou.order_id AND tou.deleted = 0
+            LEFT JOIN trade_detail tdl ON td.id = tdl.order_id AND tdl.deleted = 0
+            LEFT JOIN trade_visitor tv ON tdl.id = tv.detail_id AND tv.deleted = 0
+            LEFT JOIN (
+            SELECT order_id, SUM(pay_amount) AS actual_amount
+            FROM trade_order_pay
+            WHERE pay_status = 1
+            GROUP BY order_id
+            ) topay ON td.id = topay.order_id
+        WHERE
+            td.deleted = 0
+            AND tv.type IS NOT NULL
+            <include refid="commonWhereConditions"/>
+        GROUP BY td.id, td.pay_amount) a
+
+    </select>
+
+    <!-- 公共查询条件 -->
+    <sql id="commonWhereConditions">
+        <if test="vo.orderStatus!=null and vo.orderStatus.size()>0">
+            AND td.order_status IN
+            <foreach collection="vo.orderStatus" item="item" separator="," open="(" close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="vo.tenantId!=null">
+            AND td.tenant_id = #{vo.tenantId}
+        </if>
+        <choose>
+            <when test="vo.orderNo != null and vo.orderNo.length() == 4">
+                AND td.order_no LIKE CONCAT('%',#{vo.orderNo})
+            </when>
+            <when test="vo.orderNo != null and vo.orderNo != ''">
+                AND td.order_no = #{vo.orderNo}
+            </when>
+            <otherwise>
+            </otherwise>
+        </choose>
+
+        <if test="vo.externalOriginOrderNo != null and vo.externalOriginOrderNo != ''">
+            AND td.external_origin_order_no = #{vo.externalOriginOrderNo}
+        </if>
+
+        <if test="vo.memberId != null and vo.memberId != ''">
+            AND td.member_id = #{vo.memberId}
+        </if>
+        <if test="vo.voyageId != null and vo.voyageId != ''">
+            AND td.voyage_id = #{vo.voyageId}
+        </if>
+        <if test="vo.shipId != null and vo.shipId != ''">
+            AND td.ship_id = #{vo.shipId}
+        </if>
+        <if test="vo.routeId != null and vo.routeId != ''">
+            AND EXISTS (SELECT 1 FROM product_voyage top WHERE top.id = td.voyage_id AND top.route_id = #{vo.routeId})
+        </if>
+        <if test="vo.dispatchStatus != null">
+            AND td.dispatch_status = #{vo.dispatchStatus}
+        </if>
+        <if test="vo.payType != null">
+            AND EXISTS (SELECT 1 FROM trade_order_pay top WHERE top.order_id = td.id AND top.payment_type = #{vo.payType})
+        </if>
+        <if test="vo.otaCateId != null and vo.otaCateId != ''">
+            AND od.ota_category_id = #{vo.otaCateId}
+        </if>
+        <if test="vo.otaCateIds!=null and vo.otaCateIds.size()>0">
+            AND od.ota_category_id IN
+            <foreach collection="vo.otaCateIds" item="item" separator="," open="(" close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="vo.otaId != null and vo.otaId != ''">
+            AND td.source_id = #{vo.otaId}
+        </if>
+        <if test="vo.storeId != null and vo.storeId != ''">
+            AND td.store_id = #{vo.storeId}
+        </if>
+        <if test="vo.productTag != null and vo.productTag != ''">
+            AND ps.product_tag = #{vo.productTag}
+        </if>
+        <if test="vo.productTag2 != null and vo.productTag2 != ''">
+            AND ps.product_tag2 = #{vo.productTag2}
+        </if>
+        <if test="vo.productTag3 != null and vo.productTag3 != ''">
+            AND ps.product_tag3 = #{vo.productTag3}
+        </if>
+        <if test="vo.productTag4 != null and vo.productTag4 != ''">
+            AND ps.product_tag4 = #{vo.productTag4}
+        </if>
+        <if test="vo.cateIds!=null and vo.cateIds.size()>0 and (vo.planIds==null or vo.planIds.size()==0)">
+            AND tdl.product_id IN
+            <foreach collection="vo.cateIds" item="item" separator="," open="(" close=")">
+                #{item}
+            </foreach>
+        </if>
+
+        <if test="vo.externalOrderNo != null and vo.externalOrderNo != ''">
+            AND td.external_order_no = #{vo.externalOrderNo}
+        </if>
+        <if test="vo.credentialNo != null and vo.credentialNo != ''">
+            AND EXISTS (SELECT tv.id FROM trade_visitor tv WHERE tv.detail_id = tdl.id AND tv.credential_no = #{vo.credentialNo})
+        </if>
+        <if test="vo.userName != null and vo.userName != ''">
+            AND EXISTS (SELECT tv.id FROM trade_visitor tv WHERE tv.detail_id = tdl.id AND tv.name = #{vo.userName})
+        </if>
+        <choose>
+            <when test="vo.mobile != null and vo.mobile.length() == 4">
+                AND tou.mobile LIKE CONCAT('%',#{vo.mobile})
+            </when>
+            <when test="vo.mobile != null and vo.mobile != ''">
+                AND tou.mobile = #{vo.mobile}
+            </when>
+            <otherwise>
+            </otherwise>
+        </choose>
+        <if test="vo.contactName != null and vo.contactName != ''">
+            AND tou.contact_name = #{vo.contactName}
+        </if>
+        <if test="vo.travelDate != null and vo.travelDate != ''">
+            AND td.travel_date = #{vo.travelDate}
+        </if>
+        <if test="vo.travelDateStart != null and vo.travelDateStart != ''">
+            AND td.travel_date <![CDATA[ >= ]]> #{vo.travelDateStart}
+        </if>
+        <if test="vo.travelDateEnd != null and vo.travelDateEnd != ''">
+            AND td.travel_date <![CDATA[ <= ]]> #{vo.travelDateEnd}
+        </if>
+        <if test="vo.orderDateStart != null and vo.orderDateStart != ''">
+            AND td.create_time <![CDATA[ >= ]]> #{vo.orderDateStart}
+        </if>
+        <if test="vo.orderDateEnd != null and vo.orderDateEnd != ''">
+            AND td.create_time <![CDATA[ <= ]]> #{vo.orderDateEnd}
+        </if>
+        <if test="vo.orderDate != null and vo.orderDate != ''">
+            AND td.create_time = #{vo.orderDate}
+        </if>
+        <if test="vo.sellerId != null and vo.sellerId != ''">
+            AND td.seller_id = #{vo.sellerId}
+        </if>
+        <if test="vo.shareName != null and vo.shareName != ''">
+            AND td.share_name LIKE CONCAT('%',#{vo.shareName},'%')
+        </if>
+        <if test="vo.voucherCode != null and vo.voucherCode != ''">
+            AND tdl.voucher_code = #{vo.voucherCode}
+        </if>
+        <if test="vo.sellMethod != null and vo.sellMethod != ''">
+            AND td.sell_method = #{vo.sellMethod}
+        </if>
+        <if test="vo.productName != null and vo.productName != ''">
+            AND tdl.product_name LIKE CONCAT('%',#{vo.productName}, '%')
+        </if>
+        <if test="vo.isFullPay == 0">
+            AND td.is_full_pay = #{vo.isFullPay}
+        </if>
+        <if test="vo.isComment != null">
+            AND td.is_comment = #{vo.isComment}
+        </if>
+        <if test="vo.sourceId != null and vo.sourceId != ''">
+            AND td.source_id = #{vo.sourceId}
+        </if>
+        <if test="vo.distributorId != null and vo.distributorId != ''">
+            AND td.source_id = #{vo.distributorId}
+        </if>
+        <if test="vo.sourceName != null and vo.sourceName != ''">
+            AND td.source_name LIKE CONCAT('%',#{vo.sourceName}, '%')
+        </if>
+        <if test="vo.travelStatus != null">
+            AND td.travel_status = #{vo.travelStatus}
+        </if>
+        <if test="vo.roomModelId != null and vo.roomModelId != ''">
+            AND torm.room_model_id = #{vo.roomModelId}
+        </if>
+        <if test="vo.floor != null and vo.floor != ''">
+            AND torm.floor = #{vo.floor}
+        </if>
+        <if test="vo.orderRefundDateStart != null and vo.orderRefundDateEnd != ''">
+            AND EXISTS (SELECT 1 FROM trade_refund tr WHERE tr.order_id=td.id AND tr.refund_status = 6 AND tr.refund_time BETWEEN #{vo.orderRefundDateStart} and #{vo.orderRefundDateEnd})
+        </if>
+    </sql>
+
     <select id="getTradeOrderUserPage"
             resultType="com.yc.ship.module.trade.controller.admin.order.vo.order.TradeOrderRespVO">
         SELECT td.*,toa.audit_time auditTime,tou.contact_name,tou.credential_no,tou.mobile,count(tdl.id) num,sum(CASE WHEN tdl.voucher_status in (1,2,3,4,6,8,9) THEN	1 ELSE 0 END) realnum,(tr.origin_amount-tr.refund_amount) feeAmount,tdl.product_name,tdl.spec_type,ifnull(tr.origin_amount-tr.refund_amount,0) realAmount