Browse Source

Merge branch 'main' of http://117.174.100.38:3000/lishiqiang/ship-ota-server into main1

luofeiyun 2 weeks ago
parent
commit
a930098a8d
26 changed files with 724 additions and 643 deletions
  1. 5 2
      ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/api/invoice/dto/InvoicingReqDTO.java
  2. 22 4
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/AdminTradeOrderController.java
  3. 16 1
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/OtcTradeOrderController.java
  4. 3 2
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/OrderTotalRespVO.java
  5. 30 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TouristExportVisitorVO.java
  6. 10 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderRespExcelVO.java
  7. 5 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/dataobject/invoice/InvoiceDO.java
  8. 7 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/mysql/order/TradeOrderMapper.java
  9. 6 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/mysql/order/TradeVisitorMapper.java
  10. 0 33
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/InvoiceHangxinService.java
  11. 0 7
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/InvoiceService.java
  12. 75 39
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/impl/InvoiceGroupServiceImpl.java
  13. 0 434
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/impl/InvoiceHangxinServiceImpl.java
  14. 18 89
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/impl/InvoiceServiceImpl.java
  15. 14 16
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/impl/InvoiceSxlyServiceImpl.java
  16. 2 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/AdminTradeOrderService.java
  17. 1 1
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/TradeOrderService.java
  18. 76 4
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/impl/AdminTradeOrderServiceImpl.java
  19. 1 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/impl/TradeOrderRepositoryServiceImpl.java
  20. 5 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/OtcTradeOrderService.java
  21. 103 4
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/impl/OtcTradeOrderServiceImpl.java
  22. 1 1
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/smsSendconfig/MessageSendServiceImpl.java
  23. 154 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/utils/excel/ExcelStyleHandler.java
  24. 85 5
      ship-module-trade/ship-module-trade-biz/src/main/resources/mapper/order/TradeOrderMapper.xml
  25. 85 1
      ship-module-trade/ship-module-trade-biz/src/main/resources/mapper/order/TradeVisitorMapper.xml
  26. BIN
      ship-module-trade/ship-module-trade-biz/src/main/resources/templates/tourist_template.xlsx

+ 5 - 2
ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/api/invoice/dto/InvoicingReqDTO.java

@@ -39,12 +39,15 @@ public class InvoicingReqDTO {
     private String buyerEmail;
 
     /** 开票金额 */
-    @Schema(description = "开票金额",example="")
+    @Schema(description = "开票金额(总金额)",example="")
     private BigDecimal totalPrice;
 
-    @Schema(description = "当前开票金额",example="")
+    @Schema(description = "当前开票金额(实际金额)",example="")
     private BigDecimal price;
 
+    @Schema(description = "当前开票折扣金额",example="")
+    private BigDecimal zkprice;
+
     /** 买方地址 */
     @Schema(description = "买方地址",example="")
     private String buyerAddress;

+ 22 - 4
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/AdminTradeOrderController.java

@@ -5,27 +5,28 @@ import com.yc.ship.framework.common.pojo.CommonResult;
 import com.yc.ship.framework.common.util.collection.CollectionUtils;
 import com.yc.ship.framework.common.util.collection.MapUtils;
 import com.yc.ship.framework.common.util.object.BeanUtils;
+import com.yc.ship.framework.operatelog.core.annotations.OperateLog;
 import com.yc.ship.module.member.api.user.MemberUserApi;
 import com.yc.ship.module.member.api.user.dto.MemberUserRespDTO;
 import com.yc.ship.module.system.api.user.AdminUserApi;
 import com.yc.ship.module.system.api.user.dto.AdminUserRespDTO;
 import com.yc.ship.module.trade.controller.admin.order.vo.order.TradeOrderLogRespVO;
 import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderLogDO;
+import com.yc.ship.module.trade.framework.annotation.PlatTenantEnv;
+import com.yc.ship.module.trade.service.order.AdminTradeOrderService;
 import com.yc.ship.module.trade.service.order.TradeOrderLogService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import java.util.List;
 import java.util.Map;
 
 import static com.yc.ship.framework.common.pojo.CommonResult.success;
+import static com.yc.ship.framework.operatelog.core.enums.OperateTypeEnum.API;
 
 /**
  * 后台管理:订单通用接口
@@ -46,6 +47,9 @@ public class AdminTradeOrderController {
     @Resource
     private MemberUserApi memberUserApi;
 
+    @Resource
+    private AdminTradeOrderService adminTradeOrderService;
+
     @GetMapping("getOrderLogListByOrderId")
     @Operation(summary = "通过订单ID获得订单日志列表")
     public CommonResult<List<TradeOrderLogRespVO>> getOrderLogListByOrderId(@RequestParam("orderNo")  String orderNo) {
@@ -68,5 +72,19 @@ public class AdminTradeOrderController {
         });
         return success(tradeOrderLogRespVoList);
     }
+    @PostMapping("/order-apply-invoice")
+    @Operation(summary = "订单开票")
+    @OperateLog(type = API)
+    @PlatTenantEnv
+    public CommonResult<?> orderApplyInvoice(@RequestBody String jsonstr){
+        return  adminTradeOrderService.orderApplyInvoice(jsonstr);
+    }
 
+    @PostMapping("/plat-apply-invoice")
+    @Operation(summary = "平台订单开票")
+    @OperateLog(type = API)
+    @PlatTenantEnv
+    public CommonResult<?> platApplyInvoice(@RequestBody String jsonstr){
+        return  adminTradeOrderService.platApplyInvoice(jsonstr);
+    }
 }

+ 16 - 1
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/OtcTradeOrderController.java

@@ -616,8 +616,23 @@ public class OtcTradeOrderController {
 
     @PostMapping("/getOrderTotal")
     @Operation(summary = "获取订单统计")
-    @OperateLog(type = API, enable = false)
+    @OperateLog(type = API)
     public CommonResult<OrderTotalRespVO> getOrderTotal(@Valid @RequestBody OrderTotalQueryVO queryVO) {
         return success(otcTradeOrderService.getOrderTotal(queryVO));
     }
+
+    /**
+     * 导出游客名单
+     */
+    @GetMapping("/export-touristExcel")
+    @Operation(summary = "导出游客名单 Excel")
+    @OperateLog(type = EXPORT, enable = false)
+    @PlatTenantEnv
+    public void exportTouristList(@Valid TradeOrderPageReqVO pageReqVO, HttpServletResponse response) throws IOException {
+        File tempFile = otcTradeOrderService.exportTouristList(pageReqVO);
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setHeader("Content-Disposition", "attachment; filename=" + tempFile.getName());
+        InputStream is = Files.newInputStream(tempFile.toPath());
+        IOUtils.copy(is, response.getOutputStream());
+    }
 }

+ 3 - 2
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/OrderTotalRespVO.java

@@ -98,7 +98,7 @@ public class OrderTotalRespVO {
      */
     @Schema(description = "代收服务费")
     private BigDecimal collectionServiceMoney;
-
+    //order
     @Schema(description = "定金")
     private BigDecimal deposi;
 
@@ -107,10 +107,11 @@ public class OrderTotalRespVO {
 
     @Schema(description = "总加床数")
     private BigDecimal totalAddBedNum;
-
+    //order
     @Schema(description = "实收款房数")
     private BigDecimal totalPayedRoomNum;
 
+    //order
     @Schema(description = "未收款房数")
     private BigDecimal totalNotPayRoomNum;
 

+ 30 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TouristExportVisitorVO.java

@@ -0,0 +1,30 @@
+package com.yc.ship.module.trade.controller.admin.order.vo.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * 游客名单导出 - 游客信息VO
+ */
+@Schema(description = "游客名单导出 - 游客信息")
+@Data
+public class TouristExportVisitorVO {
+
+    @Schema(description = "游客姓名")
+    private String name;
+
+    @Schema(description = "国籍名称")
+    private String nationalityName;
+
+    @Schema(description = "证件类型")
+    private Integer credentialType;
+
+    @Schema(description = "证件号")
+    private String credentialNo;
+
+    @Schema(description = "生日")
+    private String birthday;
+
+    @Schema(description = "备注")
+    private String remark;
+}

+ 10 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderRespExcelVO.java

@@ -42,6 +42,11 @@ public class TradeOrderRespExcelVO {
     @DictFormat("system_user_sex")
     private Integer gender;
 
+    @Schema(description = "证件类型")
+    @ExcelProperty(value = "证件类型", converter = DictConvert.class)
+    @DictFormat("credential_type")
+    private String credentialType;
+
     @Schema(description = "证件号")
     @ExcelProperty("证件号")
     private String credentialNo;
@@ -50,6 +55,11 @@ public class TradeOrderRespExcelVO {
     @ExcelProperty("国籍")
     private String nationality;
 
+    @Schema(description = "客户类型")
+    @ExcelProperty(value = "客户类型", converter = DictConvert.class)
+    @DictFormat("tour_type")
+    private String visitorType;
+
     @Schema(description = "生日")
     @ExcelProperty("生日")
     private String birthday;

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

@@ -118,6 +118,11 @@ public class InvoiceDO extends TenantBaseDO {
      * 开票金额
      */
     private BigDecimal price;
+
+    /**
+     * 折扣金额
+     */
+    private BigDecimal zkprice;
     /**
      * 发票请求流水号
      */

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

@@ -186,4 +186,11 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
     List<TradeOrderConfirmationCountryRespVO> selectConfirmationCountry(@Param("orderId") Long orderId);
 
     Map<String, Object> getOrderCount(@Param("vo") TradeOrderPageReqVO pageReqVO);
+
+    OrderTotalRespVO selectTotalByOrderIds(@Param("orderIds") List<Long> orderIds);
+
+    /**
+     * 查询游客名单导出基础信息(船名、航期、航向)
+     */
+    Map<String, Object> selectTouristExportBase(@Param("vo") TradeOrderPageReqVO reqVO);
 }

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

@@ -5,6 +5,7 @@ import com.yc.ship.framework.common.pojo.PageResult;
 import com.yc.ship.framework.mybatis.core.mapper.BaseMapperX;
 import com.yc.ship.framework.tenant.core.aop.TenantIgnore;
 import com.yc.ship.module.product.api.dto.OrderRoomUseDTO;
+import com.yc.ship.module.trade.controller.admin.order.vo.order.TouristExportVisitorVO;
 import com.yc.ship.module.trade.controller.admin.order.vo.order.TradeOrderPageReqVO;
 import com.yc.ship.module.trade.controller.admin.order.vo.order.TradeOrderRespExcelVO;
 import com.yc.ship.module.trade.controller.admin.order.vo.order.TradeVisitorRespVO;
@@ -79,4 +80,9 @@ public interface TradeVisitorMapper extends BaseMapperX<TradeVisitorDO> {
     List<TradeVisitorDO> selectListByVoyageIdAndRoomId(@Param("voyageId")Long voyageId, @Param("roomId")Long roomId);
 
     List<TradeOrderRespExcelVO> getExportVisitorList(@Param("vo") TradeOrderPageReqVO reqVO);
+
+    /**
+     * 查询游客名单导出游客列表
+     */
+    List<TouristExportVisitorVO> selectTouristExportVisitor(@Param("vo") TradeOrderPageReqVO reqVO);
 }

+ 0 - 33
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/InvoiceHangxinService.java

@@ -1,33 +0,0 @@
-package com.yc.ship.module.trade.service.invoice;
-
-import cn.hutool.json.JSONObject;
-import com.yc.ship.framework.common.pojo.CommonResult;
-import com.yc.ship.module.trade.dal.dataobject.invoice.InvoiceDO;
-
-public interface InvoiceHangxinService {
-
-    Boolean login (String username, String password);
-
-    /**
-     *  登录第一步(申请登录)
-     * @param username
-     * @param password
-     * @param userIdentity
-     * @return
-     */
-    JSONObject loginStepOne(String username, String password,String userIdentity);
-
-    /**
-     * 登录第二步(确认登录)
-     * @param username
-     * @param smsCode
-     * @return
-     */
-    JSONObject loginStepTwo(String username,String smsCode);
-
-    CommonResult<InvoiceDO> invoiceIssuance (InvoiceDO invoice);
-
-    JSONObject queryInvoiceUrl (Long invoiceId , String invoiceNo, String invoiceDate);
-
-
-}

+ 0 - 7
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/InvoiceService.java

@@ -25,13 +25,6 @@ public interface InvoiceService {
     CommonResult applyReInvoicing(InvoicingReqDTO reqDTO);
 
 
-    /**
-     * 查询发票url
-     *
-     * @param id
-     * @return
-     */
-    String queryInvoiceUrl(InvoiceDO invoice);
 
     List<InvoiceDO> queryInvoiceOrder(String orderNo);
 

File diff suppressed because it is too large
+ 75 - 39
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/impl/InvoiceGroupServiceImpl.java


File diff suppressed because it is too large
+ 0 - 434
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/impl/InvoiceHangxinServiceImpl.java


+ 18 - 89
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/impl/InvoiceServiceImpl.java

@@ -1,11 +1,9 @@
 package com.yc.ship.module.trade.service.invoice.impl;
 
-import cn.hutool.core.date.DatePattern;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.RandomUtil;
-import cn.hutool.json.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.yc.ship.framework.common.lang.Asserts;
@@ -20,14 +18,12 @@ import com.yc.ship.module.trade.api.invoice.dto.InvoicingReqDTO;
 import com.yc.ship.module.trade.controller.admin.invoice.vo.InvoicePageReqVO;
 import com.yc.ship.module.trade.controller.admin.invoice.vo.InvoiceRespVO;
 import com.yc.ship.module.trade.dal.dataobject.invoice.InvoiceDO;
-import com.yc.ship.module.trade.dal.dataobject.invoice.InvoiceDetailDO;
 import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderDO;
 import com.yc.ship.module.trade.dal.mysql.invoice.InvoiceMapper;
 import com.yc.ship.module.trade.enums.SellMethodEnum;
 import com.yc.ship.module.trade.enums.invoice.InvoiceStatusEnum;
 import com.yc.ship.module.trade.service.invoice.InvoiceDetailService;
 import com.yc.ship.module.trade.service.invoice.InvoiceGroupService;
-import com.yc.ship.module.trade.service.invoice.InvoiceHangxinService;
 import com.yc.ship.module.trade.service.invoice.InvoiceService;
 import com.yc.ship.module.trade.service.order.TradeOrderRepositoryService;
 import com.yc.ship.module.trade.service.refund.TradeRefundRepositoryService;
@@ -48,11 +44,9 @@ import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
-import java.util.stream.Collectors;
 
 import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception0;
-import static com.yc.ship.module.trade.enums.ApiConstants.ORDER_CHANGE_TYPE_OLD;
 import static com.yc.ship.module.trade.enums.ErrorCodeConstants.*;
 
 
@@ -70,8 +64,6 @@ public class InvoiceServiceImpl implements InvoiceService {
     private InvoiceMapper invoiceMapper;
     @Resource
     private InvoiceGroupService invoiceGroupService;
-    @Resource
-    private InvoiceHangxinService invoiceHangxinService;
 
     //TODO 待完善
     @Resource
@@ -104,6 +96,7 @@ public class InvoiceServiceImpl implements InvoiceService {
                 throw exception0(500, "订单开票失败,开票金额不能为"+reqDTO.getTotalPrice());
             }
         }
+        BigDecimal zk = BigDecimal.ZERO;
         //查询订单及金额
         for (String orderNo : reqDTO.getOrderIdList()) {
             TradeOrderDO order = tradeOrderRepositoryService.getOrderByNo(orderNo);
@@ -114,26 +107,20 @@ public class InvoiceServiceImpl implements InvoiceService {
             if (order.getIsInvoice() != null && ObjectUtil.equals(order.getIsInvoice(), InvoiceStatusEnum.INVOICE_SUCCESS.getValue())) {
                 throw exception0(500, "订单{}已开票", orderNo);
             }
+
             Asserts.isTrue(ObjectUtil.equals(order.getIsInvoice(), InvoiceStatusEnum.NOT_INVOICED.getValue())
                     || ObjectUtil.equals(order.getIsInvoice(), InvoiceStatusEnum.INVOICE_FAILED.getValue()), ORDER_INVOICED.getCode(), "订单{}已开票", orderNo);
-            if(ObjectUtil.equals(order.getIsChangeOrder(),ORDER_CHANGE_TYPE_OLD)){
-                //如果是改签原订单,只计算退款手续费
-                BigDecimal totalFee = tradeRefundRepositoryService.getOrderRefundFee(order.getId());
-                if (totalFee != null) {
-                    amt = amt.add(totalFee);
-                }
-            }else{
-                amt = amt.add(order.getPayAmount());
-                //减去退款金额
-                BigDecimal orderRefundAmount = tradeRefundRepositoryService.getOrderRefundAmount(order.getId());
-                if (orderRefundAmount != null) {
-                    amt = amt.subtract(orderRefundAmount);
-                }
-                //减去未使用金额
-                BigDecimal unusedAmount = tradeOrderRepositoryService.getUnUsedAmount(order.getId());
-                if (unusedAmount != null) {
-                    amt = amt.subtract(unusedAmount);
-                }
+            amt = amt.add(order.getPayAmount());
+            zk=zk.add(order.getAmount().subtract(order.getPayAmount()));
+            //减去退款金额
+            BigDecimal orderRefundAmount = tradeRefundRepositoryService.getOrderRefundAmount(order.getId());
+            if (orderRefundAmount != null) {
+                amt = amt.subtract(orderRefundAmount);
+            }
+            //减去未使用金额
+            BigDecimal unusedAmount = tradeOrderRepositoryService.getUnUsedAmount(order.getId());
+            if (unusedAmount != null) {
+                amt = amt.subtract(unusedAmount);
             }
             orderList.add(order);
             if (StringUtils.isBlank(reqDTO.getAccountId()) && Objects.equals(order.getSellMethod(), SellMethodEnum.MINI_APP.getType())) {
@@ -143,12 +130,11 @@ public class InvoiceServiceImpl implements InvoiceService {
         if (reqDTO.getTotalPrice() == null) {
             reqDTO.setTotalPrice(reqDTO.getPrice());
         }
-        boolean isSingInvoice = false;
+        reqDTO.setZkprice(zk);
         //计算开票金额,如果未传值则用订单总金额
         if (reqDTO.getPrice() == null) {
             reqDTO.setPrice(amt);
         } else {
-            isSingInvoice = true;
             Asserts.isTrue(amt.compareTo(reqDTO.getTotalPrice()) == 0, "开票金额发生变更,请重新刷新后发起,{},{}", reqDTO.getPrice(), amt);
         }
 
@@ -157,41 +143,13 @@ public class InvoiceServiceImpl implements InvoiceService {
 
         tradeOrderRepositoryService.updateInvoiceStatus(orderList, InvoiceStatusEnum.INVOICE_INVOIING.getValue());
         String fpSupplier = configApi.getPlatformConfigValueByKey("supplier");
-        CommonResult<InvoiceDO> result;
         invoiceDO.setFpSupplier(fpSupplier);
-        if (StringUtils.equals("group", fpSupplier)) {
-            result = invoiceGroupService.invoiceIssuance(invoiceDO,reqDTO.getRemark());
-        } else {
-            result = invoiceHangxinService.invoiceIssuance(invoiceDO);
-        }
+        CommonResult<InvoiceDO> result = invoiceGroupService.invoiceIssuance(invoiceDO,reqDTO.getRemark());
         if (result.isSuccess()) {
             tradeOrderRepositoryService.updateInvoiceStatus(orderList, InvoiceStatusEnum.INVOICE_SUCCESS.getValue());
         } else {
             tradeOrderRepositoryService.updateInvoiceStatus(orderList, InvoiceStatusEnum.INVOICE_FAILED.getValue());
         }
-
-
-        if(isSingInvoice && reqDTO.getTotalPrice().subtract(reqDTO.getPrice()).compareTo(BigDecimal.ZERO)>0){
-            InvoiceDO invoiceDO2 = this.buildInvoice(reqDTO, reqDTO.getTotalPrice().subtract(reqDTO.getPrice()));
-            invoiceDetailService.createInvoiceDetail(orderList, invoiceDO2.getId());
-
-            tradeOrderRepositoryService.updateInvoiceStatus(orderList, InvoiceStatusEnum.INVOICE_INVOIING.getValue());
-            CommonResult<InvoiceDO> result2;
-            invoiceDO2.setFpSupplier(fpSupplier);
-            if (StringUtils.equals("group", fpSupplier)) {
-                result2 = invoiceGroupService.invoiceIssuance(invoiceDO2,reqDTO.getRemark());
-            } else {
-                result2 = invoiceHangxinService.invoiceIssuance(invoiceDO2);
-            }
-            if (result2.isSuccess()) {
-                tradeOrderRepositoryService.updateInvoiceStatus(orderList, InvoiceStatusEnum.INVOICE_SUCCESS.getValue());
-            }
-//            else {
-                //第二张发票失败了不处理,可能另外一个发票已经成功
-                //tradeOrderRepositoryService.updateInvoiceStatus(orderList, InvoiceStatusEnum.INVOICE_FAILED.getValue());
-//            }
-        }
-
         return result;
 
     }
@@ -205,11 +163,8 @@ public class InvoiceServiceImpl implements InvoiceService {
 //        CompletableFuture<CommonResult<InvoiceDO>> future = CompletableFuture.supplyAsync(() -> invoiceHangxinService.invoiceIssuance(invoiceDO), executor);
         String fpSupplier = configApi.getPlatformConfigValueByKey("invoice.supplier");
         CompletableFuture<CommonResult<InvoiceDO>> future = CompletableFuture.supplyAsync(() -> {
-            if (StringUtils.equals("group", fpSupplier)) {
                 return invoiceGroupService.invoiceIssuance(invoiceDO,reqDTO.getRemark());
-            } else {
-                return invoiceHangxinService.invoiceIssuance(invoiceDO);
-            }
+
         }, executor);
         future.thenAcceptAsync(result -> {
             if (result.isSuccess()) {
@@ -223,27 +178,6 @@ public class InvoiceServiceImpl implements InvoiceService {
 
     }
 
-    @Override
-    public String queryInvoiceUrl(InvoiceDO invoice) {
-        if (invoice == null) {
-            throw exception(INVOICE_NOT_EXISTS);
-        }
-        Asserts.isTrue(invoice.getInvoiceStatus().equals(InvoiceStatusEnum.INVOICE_SUCCESS.getValue()), "发票未开票成功,无法查询!");
-        String kprq = DateUtil.format(invoice.getCKprq(), DatePattern.PURE_DATETIME_PATTERN);
-        JSONObject resObj = invoiceHangxinService.queryInvoiceUrl(invoice.getId(), invoice.getCFphm(), kprq);
-        String resultUrl = "";
-        if (null != resObj) {
-            resultUrl = resObj.getStr("DATA");
-            List<InvoiceDetailDO> list = invoiceDetailService.getInvoiceDetails(invoice.getId());
-            List<String> orderNoList = list.stream().map(InvoiceDetailDO::getOrderNo).collect(Collectors.toList());
-            //TODO:
-//            tradeOrderRepositoryService.updateInvoiceStatusByOrderNo(orderNoList, 1);
-            invoice.setCUrl(resultUrl);
-            invoiceMapper.updateById(invoice);
-        }
-        return resultUrl;
-    }
-
     @Override
     public String queryGroupInvoiceUrl(InvoiceDO invoice) {
         if (invoice == null) {
@@ -255,12 +189,6 @@ public class InvoiceServiceImpl implements InvoiceService {
         return "";
     }
 
-    private void validateInvoiceExists(Long id) {
-        if (invoiceMapper.selectById(id) == null) {
-            throw exception(INVOICE_NOT_EXISTS);
-        }
-    }
-
 
     @Override
     public InvoiceDO getInvoice(Long id) {
@@ -301,7 +229,7 @@ public class InvoiceServiceImpl implements InvoiceService {
 
     private InvoiceDO buildInvoice(InvoicingReqDTO reqDTO, BigDecimal price) {
         InvoiceDO invoiceDO = BeanUtils.toBean(reqDTO, InvoiceDO.class);
-        String taxCode = configApi.getPlatformConfigValueByKey("invoice.tax");
+        String taxCode = configApi.getPlatformConfigValueByKey("newinvoice.group.tax");
         String serialNum = RandomUtil.randomNumbers(30 - taxCode.length());
         long id = IdWorker.getId(invoiceDO);
         invoiceDO.setId(id);
@@ -317,6 +245,7 @@ public class InvoiceServiceImpl implements InvoiceService {
         invoiceDO.setTransactionNo(tradeUUCodeUtils.generateOrderNo(INVOICE_PREFIX));
         invoiceDO.setSalesTaxCode(taxCode);
         invoiceDO.setFpqqlsh(serialNum);
+        invoiceDO.setZkprice(reqDTO.getZkprice());
         invoiceDO.setSalesName(configApi.getPlatformConfigValueByKey("invoice.sales.name"));
         invoiceDO.setSalesAddress(configApi.getPlatformConfigValueByKey("invoice.sales.addr"));
         invoiceDO.setDeleted(false);

+ 14 - 16
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/invoice/impl/InvoiceSxlyServiceImpl.java

@@ -44,11 +44,9 @@ public class InvoiceSxlyServiceImpl implements InvoiceSxlyService {
     private InvoiceService invoiceService;
 
 
-
     private final String SUCCESS = "0000";
 
 
-
     /**
      * 开蓝票
      */
@@ -132,7 +130,7 @@ public class InvoiceSxlyServiceImpl implements InvoiceSxlyService {
      * @return
      */
     private JSONObject bulidRequestParam(InvoiceDO invoice) {
-        String taxNum = configApi.getPlatformConfigValueByKey("newinvoice.tax");
+        String taxNum = configApi.getPlatformConfigValueByKey("newinvoice.group.tax");
         String senid = RandomUtil.randomNumbers(30 - taxNum.length());
         //流水号(生成规则:税号 +随机数 长度为30 唯一值)
         String serialNo = taxNum + senid;
@@ -160,17 +158,17 @@ public class InvoiceSxlyServiceImpl implements InvoiceSxlyService {
         //开票类型0-蓝票
         reqObj.put("KPLX", "0");
         //发票种类代码01-专用发票 02-普通发票
-        if(invoice.getInvoiceType()==null){
+        if (invoice.getInvoiceType() == null) {
             reqObj.put("FPZLDM", "02");
-        }else {
+        } else {
             reqObj.put("FPZLDM", InvoiceTypeEnum.valueOf(invoice.getInvoiceType()).getCode());
         }
         //开票员,以电子税局绑定人员为准
         reqObj.put("KPR", invoice.getBuyerClerk());
         //销货方开户行
-        reqObj.put("XHFKHH", configApi.getPlatformConfigValueByKey("invoice.sales.bank"));
+        reqObj.put("XHFKHH", configApi.getPlatformConfigValueByKey("newinvoice.sales.bank"));
         //getPlatformConfigValueByKey
-        reqObj.put("XHFYHZH", configApi.getPlatformConfigValueByKey("invoice.sales.bankaccount"));
+        reqObj.put("XHFYHZH", configApi.getPlatformConfigValueByKey("newinvoice.sales.bankaccount"));
 
         JSONArray detailArray = new JSONArray();
         JSONObject detailObj = null;
@@ -184,15 +182,15 @@ public class InvoiceSxlyServiceImpl implements InvoiceSxlyService {
         detailObj = new JSONObject();
         detailObj.put("XH", index);
         //商品名称
-        detailObj.put("SPMC", configApi.getPlatformConfigValueByKey("invoice.goods.name"));
-        String GoodsCode = configApi.getPlatformConfigValueByKey("invoice.goods.code");
+        detailObj.put("SPMC", configApi.getPlatformConfigValueByKey("newinvoice.goods.name"));
+        String GoodsCode = configApi.getPlatformConfigValueByKey("newinvoice.goods.code");
         String spbm = StrUtil.padAfter(GoodsCode, 19, "0");
         //商品编码
         detailObj.put("SPBM", spbm);
         //商品简码
-        detailObj.put("SPJM", "*" + configApi.getPlatformConfigValueByKey("invoice.goods.simpleCode") + "*");
+        detailObj.put("SPJM", "*" + configApi.getPlatformConfigValueByKey("newinvoice.goods.simpleCode") + "*");
         //税率
-        BigDecimal taxRate = new BigDecimal(configApi.getPlatformConfigValueByKey("invoice.taxRate"));
+        BigDecimal taxRate = new BigDecimal(configApi.getPlatformConfigValueByKey("newinvoice.taxRate"));
         detailObj.put("SLV", taxRate);
         //含税金额
         BigDecimal taxIncludedAmount = invoice.getPrice();
@@ -237,9 +235,9 @@ public class InvoiceSxlyServiceImpl implements InvoiceSxlyService {
      * @throws Exception
      */
     private String sendRequest(JSONObject reqBody, String path, String userName) throws Exception {
-        String url = configApi.getPlatformConfigValueByKey("invoice.url");
-        String secretkey = configApi.getPlatformConfigValueByKey("invoice.secretkey");
-        String appId = configApi.getPlatformConfigValueByKey("invoice.appId");
+        String url = configApi.getPlatformConfigValueByKey("newinvoice.group.url");
+        String secretkey = configApi.getPlatformConfigValueByKey("newinvoice.group.secretkey");
+        String appId = configApi.getPlatformConfigValueByKey("newinvoice.group.secretId");
         // 加密数据
 
         String paramStr = JsonUtils.toJsonString(reqBody);
@@ -252,7 +250,7 @@ public class InvoiceSxlyServiceImpl implements InvoiceSxlyService {
         params.set("DATA", contentData);
         //电子税局登录账号
         params.set("USERNAME", userName);
-        log.error("发票请求参数:{}", url+path+"--"+JsonUtils.toJsonString(params));
+        log.error("发票请求参数:{}", url + path + "--" + JsonUtils.toJsonString(params));
         String resultStr = HttpUtil.createPost(url + path).contentType("application/json")
                 .body(JsonUtils.toJsonString(params))
                 .timeout(15000)
@@ -267,7 +265,7 @@ public class InvoiceSxlyServiceImpl implements InvoiceSxlyService {
     private String decrypt(String data) {
         String result = null;
         try {
-            String secretkey = configApi.getPlatformConfigValueByKey("invoice.secretkey");
+            String secretkey = configApi.getPlatformConfigValueByKey("newinvoice.group.secretkey");
             byte[] encryptedResponse = HexUtil.parseHexStr2Byte(data);
             byte[] decryptedData = DESUtil.decrypt(encryptedResponse, secretkey);
             result = new String(decryptedData).trim();

+ 2 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/AdminTradeOrderService.java

@@ -54,4 +54,6 @@ public interface AdminTradeOrderService {
 
     CommonResult<?> cancelRefund(Long refundId);
 
+    CommonResult<?> orderApplyInvoice(String jsonstr);
+    CommonResult<?> platApplyInvoice(String jsonstr);
 }

+ 1 - 1
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/TradeOrderService.java

@@ -10,6 +10,7 @@ import com.yc.ship.module.trade.api.dto.TradeOrderRespDTO;
 import com.yc.ship.module.trade.controller.admin.order.vo.order.*;
 import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderDO;
 
+import java.io.File;
 import java.util.List;
 
 /**
@@ -57,7 +58,6 @@ public interface TradeOrderService {
      */
     CommonResult<Long> bindOrder(TradeBindOrderReqDTO tradeBindOrderReqDTO);
 
-
     /**
      * 修改游客信息
      *

+ 76 - 4
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/impl/AdminTradeOrderServiceImpl.java

@@ -3,6 +3,8 @@ package com.yc.ship.module.trade.service.order.impl;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.yc.ship.framework.common.lang.Asserts;
@@ -11,6 +13,8 @@ import com.yc.ship.framework.common.util.collection.CollectionUtils;
 import com.yc.ship.framework.common.util.object.ObjectUtils;
 import com.yc.ship.framework.mybatis.core.query.LambdaQueryWrapperX;
 import com.yc.ship.framework.security.core.LoginUser;
+import com.yc.ship.module.ota.api.OtaDistributorApi;
+import com.yc.ship.module.ota.api.dto.DistributorRespDTO;
 import com.yc.ship.module.otc.api.agency.dto.AgencyUserLoginInfoRespDTO;
 import com.yc.ship.module.product.api.dto.ProductSpuRespDTO;
 import com.yc.ship.module.trade.api.contract.ContractApi;
@@ -20,7 +24,9 @@ import com.yc.ship.module.trade.api.dto.TradeRefundAuditReqDTO;
 import com.yc.ship.module.trade.api.dto.TradeRefundCalculateRespDTO;
 import com.yc.ship.module.trade.api.dto.TradeRefundCreateReqDTO;
 import com.yc.ship.module.trade.api.dto.TradeRefundRespDTO;
+import com.yc.ship.module.trade.api.invoice.dto.InvoicingReqDTO;
 import com.yc.ship.module.trade.controller.admin.order.vo.refund.*;
+import com.yc.ship.module.trade.convert.invoice.InvoiceConvert;
 import com.yc.ship.module.trade.convert.order.TradeRefundConvert;
 import com.yc.ship.module.trade.dal.dataobject.audituser.AuditUserDO;
 import com.yc.ship.module.trade.dal.dataobject.order.TradeDetailDO;
@@ -34,7 +40,11 @@ import com.yc.ship.module.trade.dal.mysql.order.TradeOrderMapper;
 import com.yc.ship.module.trade.dal.mysql.refund.CancelAuditMapper;
 import com.yc.ship.module.trade.dal.mysql.tradeOrderaudit.TradeOrderAuditMapper;
 import com.yc.ship.module.trade.enums.RefundChannelEnum;
+import com.yc.ship.module.trade.enums.TradeOrderOperateTypeEnum;
 import com.yc.ship.module.trade.enums.TradeOrderStatusEnum;
+import com.yc.ship.module.trade.framework.annotation.TradeOrderLog;
+import com.yc.ship.module.trade.framework.common.TradeOrderLogUtils;
+import com.yc.ship.module.trade.service.invoice.InvoiceService;
 import com.yc.ship.module.trade.service.order.AdminTradeOrderService;
 import com.yc.ship.module.trade.service.order.TradeOrderRepositoryService;
 import com.yc.ship.module.trade.service.order.bo.TradeVisitorBO;
@@ -46,10 +56,7 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -87,6 +94,10 @@ public class AdminTradeOrderServiceImpl implements AdminTradeOrderService {
     private ContractApi contractApi;
     @Resource
     private TradeOrderRepositoryService tradeOrderRepositoryService;
+    @Resource
+    private OtaDistributorApi distributorApi;
+    @Resource
+    private InvoiceService invoiceService;
 
     @Override
     public CommonResult<TradeRefundCreateRespVO> refund(LoginUser loginUser, TradeRefundCreateReqVO refundCreateReqVO) {
@@ -328,6 +339,7 @@ public class AdminTradeOrderServiceImpl implements AdminTradeOrderService {
     }
 
     @Override
+    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MANUL_CANCEL)
     public CommonResult<?> cancelOrder(Long orderId) {
         TradeOrderDO tradeOrderDO = tradeOrderRepositoryService.getById(orderId);
         Asserts.isTrue(tradeOrderDO != null, "订单不存在");
@@ -346,6 +358,7 @@ public class AdminTradeOrderServiceImpl implements AdminTradeOrderService {
 
             AuditUserDO auditUserDO = auditUserMapper.selectOne(new LambdaQueryWrapperX<AuditUserDO>().eq(AuditUserDO::getType, 4).eq(AuditUserDO::getAuditStatus, 1).eq(AuditUserDO::getDeleted, 0).orderByDesc(AuditUserDO::getCreateTime).last("limit 1"));
             tradeOrderMapper.update(new UpdateWrapper<TradeOrderDO>().set("audit_type", 4).set("audit_user", auditUserDO == null ? "" : auditUserDO.getAuditUser()).set("order_status", TradeOrderStatusEnum.CANCEL_AUDIT.getStatus()).set("audit_status", 1).eq("id", tradeOrderDO.getId()));
+            TradeOrderLogUtils.setOrderInfo(orderId, tradeOrderDO.getOrderStatus(), TradeOrderStatusEnum.CANCEL_AUDIT.getStatus());
             return CommonResult.success("订单取消审核中");
 //        }else{
 //            return tradeOrderPayService.cancelOrder(orderId);
@@ -366,4 +379,63 @@ public class AdminTradeOrderServiceImpl implements AdminTradeOrderService {
         return tradeRefundService.cancelRefund(refundId);
     }
 
+    @Override
+    public CommonResult<?> orderApplyInvoice(String jsonStr) {
+        JSONObject reqObj = JSONUtil.parseObj(jsonStr);
+        List<String> orderNoList = Arrays.asList(reqObj.getStr("orderNos").split(","));
+        String otaId = reqObj.getStr("otaId");
+        String remark = reqObj.getStr("remark");
+        if(StringUtils.isNotBlank(otaId)){
+            //平台开旅行社发票
+            DistributorRespDTO distributorRespDTO = distributorApi.getDistributorById(Long.parseLong(otaId));
+            if (distributorRespDTO==null){
+                throw exception(INVOICING_FAIL);
+            }
+            InvoicingReqDTO reqDTO = InvoiceConvert.INSTANCE.convertOtc(distributorRespDTO);
+            reqDTO.setOrderIdList(orderNoList);
+            reqDTO.setTitleType(1);
+            reqDTO.setRemark(remark);
+            reqDTO.setPrice(reqObj.getBigDecimal("amount"));
+            reqDTO.setTotalPrice(reqObj.getBigDecimal("totalAmount"));
+            return invoiceService.applyInvoicing(reqDTO);
+        }
+        LoginUser loginUser = getLoginUser();
+        CommonResult<DistributorRespDTO> distributorResult = distributorApi.getDistributorByAccountTenantId(loginUser.getTenantId());
+        if (distributorResult.isError()){
+            throw exception(INVOICING_FAIL);
+        }
+        DistributorRespDTO distributorRespDTO = distributorResult.getCheckedData();
+        InvoicingReqDTO reqDTO = InvoiceConvert.INSTANCE.convertOtc(distributorRespDTO);
+        reqDTO.setOrderIdList(orderNoList);
+        reqDTO.setTitleType(1);
+        reqDTO.setRemark(remark);
+        reqDTO.setPrice(reqObj.getBigDecimal("amount"));
+        reqDTO.setTotalPrice(reqObj.getBigDecimal("totalAmount"));
+        return invoiceService.applyInvoicing(reqDTO);
+    }
+
+    @Override
+    public CommonResult<?> platApplyInvoice(String jsonStr) {
+        JSONObject reqObj = JSONUtil.parseObj(jsonStr);
+        List<String> orderNoList = Arrays.asList(reqObj.getStr("orderNos").split(","));
+        String otaId = reqObj.getStr("otaId");
+        String remark = reqObj.getStr("remark");
+        if(StringUtils.isBlank(otaId)){
+            throw exception(INVOICING_FAIL_OTA);
+        }
+        //平台开旅行社发票
+        DistributorRespDTO distributorRespDTO = distributorApi.getDistributorById(Long.parseLong(otaId));
+        if (distributorRespDTO == null){
+            throw exception(INVOICING_FAIL);
+        }
+        InvoicingReqDTO reqDTO = InvoiceConvert.INSTANCE.convertOtc(distributorRespDTO);
+        reqDTO.setOrderIdList(orderNoList);
+        reqDTO.setTitleType(1);
+        reqDTO.setIsPlat(1);
+        reqDTO.setRemark(remark);
+        reqDTO.setPrice(reqObj.getBigDecimal("amount"));
+        reqDTO.setTotalPrice(reqObj.getBigDecimal("totalAmount"));
+        return invoiceService.applyInvoicing(reqDTO);
+    }
+
 }

+ 1 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/impl/TradeOrderRepositoryServiceImpl.java

@@ -276,6 +276,7 @@ public class TradeOrderRepositoryServiceImpl implements TradeOrderRepositoryServ
     public TradeOrderDO getOrderByNo(String orderNo) {
         LambdaQueryWrapper<TradeOrderDO> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(TradeOrderDO::getOrderNo, orderNo);
+        queryWrapper.eq(TradeOrderDO::getDeleted, 0);
 
         return tradeOrderMapper.selectOne(queryWrapper);
     }

+ 5 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/OtcTradeOrderService.java

@@ -149,4 +149,9 @@ public interface OtcTradeOrderService {
      * 获取订单统计信息
      */
     OrderTotalRespVO getOrderTotal(OrderTotalQueryVO queryVO);
+
+    /**
+     * 导出游客名单
+     */
+    File exportTouristList(TradeOrderPageReqVO pageReqVO);
 }

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

@@ -107,6 +107,7 @@ import com.yc.ship.module.trade.service.otc.OtcTradeOrderService;
 import com.yc.ship.module.trade.service.pay.TradeOrderPayService;
 import com.yc.ship.module.trade.service.refund.TradeRefundRepositoryService;
 import com.yc.ship.module.trade.utils.AgencyAuthUtils;
+import com.yc.ship.module.trade.utils.excel.ExcelStyleHandler;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.ss.usermodel.*;
@@ -589,14 +590,17 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
     @Override
     public OrderTotalRespVO getOrderTotal(OrderTotalQueryVO queryVO) {
         List<Long> orderIds = queryVO.getOrderIds();
-
+        if (orderIds == null || orderIds.isEmpty()){
+            return null;
+        }
+        OrderTotalRespVO totalMap = tradeOrderMapper.selectTotalByOrderIds(orderIds);
         //TODO: 待完善 订单合计
-        return null;
+        return totalMap;
     }
 
 
     @Override
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ORDER_AUDIT)
+    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.CANCEL_AUDIT)
     @TenantIgnore
     public CommonResult<?> cancelAuto(Long orderId) {
         TradeOrderDO tradeOrderDO = tradeOrderMapper.selectById(orderId);
@@ -1377,7 +1381,6 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
                 AdminUserRespDTO user = adminUserApi.getUser(Long.parseLong(spu.getSellerId()));
                 if (user != null) {
                     spu.setSellerName(user.getNickname());
-                    spu.setBusinessName(user.getNickname());
                 }
             }
         });
@@ -2487,4 +2490,100 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
         );
         return CommonResult.success("修改成功");
     }
+
+    @Override
+    public File exportTouristList(TradeOrderPageReqVO reqVO) {
+        // 1. 查询订单基础信息(船名、航期、航向)
+        Map<String, Object> baseInfo = tradeOrderMapper.selectTouristExportBase(reqVO);
+
+        // 2. 查询游客列表
+        List<TouristExportVisitorVO> visitorList = tradeVisitorMapper.selectTouristExportVisitor(reqVO);
+
+        // 3. 加载模板
+        InputStream template = getClass().getClassLoader().getResourceAsStream("templates/tourist_template.xlsx");
+        String fileName =  String.valueOf(System.currentTimeMillis());
+        String tmpFile = "/tmp/" + fileName + "_tourist.xlsx";
+        //String tmpFile = "D:/tmp/" + fileName + "_tourist.xlsx";
+
+        // 先不合并,直接导出
+        ExcelWriter excelWriter = EasyExcel.write(tmpFile).withTemplate(template).build();
+        WriteSheet writeSheet = EasyExcelFactory.writerSheet().registerWriteHandler(new ExcelStyleHandler(9)).build();
+        FillConfig fillConfig = FillConfig.builder().forceNewRow(true).autoStyle(true).build();
+
+        // 4. 准备基础信息数据
+        Map<String, Object> baseData = new HashMap<>();
+
+        // 船名
+        baseData.put("shipName", baseInfo != null && baseInfo.get("shipName") != null ? baseInfo.get("shipName") : "");
+
+        // 航期
+        // 航期
+        baseData.put("travelDate", baseInfo != null && baseInfo.get("travelDate") != null
+                ? ((LocalDateTime) baseInfo.get("travelDate")).format(DateTimeFormatter.ofPattern("yyyy.M.d"))
+                : "");
+
+
+        // 航向
+        Integer direction = baseInfo != null && baseInfo.get("direction") != null ? (Integer) baseInfo.get("direction") : 0;
+        baseData.put("direction", direction != null && direction == 1 ? "宜昌-重庆" : "重庆-宜昌");
+
+        // 总人数和国籍统计
+        int totalCount = visitorList != null ? visitorList.size() : 0;
+        StringBuilder countryStat = new StringBuilder();
+
+        if (visitorList != null && !visitorList.isEmpty()) {
+            Map<String, Long> countryMap = visitorList.stream()
+                    .filter(item -> ObjectUtil.isNotEmpty(item) && StringUtils.isNotEmpty(item.getNationalityName()))
+                    .collect(Collectors.groupingBy(
+                            TouristExportVisitorVO::getNationalityName,
+                            Collectors.counting()
+                    ));
+
+            for (Map.Entry<String, Long> entry : countryMap.entrySet()) {
+                if (countryStat.length() > 0) {
+                    countryStat.append(" ");
+                }
+                countryStat.append(entry.getValue()).append(" / ").append(entry.getKey());
+            }
+        }
+        baseData.put("totalCount", totalCount);
+        baseData.put("countryStat", countryStat.toString());
+
+        // 5. 准备游客明细列表
+        List<Map<String, Object>> touristData = new ArrayList<>();
+
+        if (visitorList != null) {
+            for (int i = 0; i < visitorList.size(); i++) {
+                TouristExportVisitorVO visitor = visitorList.get(i);
+                Map<String, Object> item = new HashMap<>();
+                if (ObjectUtil.isEmpty(visitor)) {
+                    continue;
+                }
+                // 序号
+                item.put("xh", i + 1);
+                // 姓名
+                item.put("name", StringUtils.isEmpty(visitor.getName()) ? "" : visitor.getName());
+                // 国籍
+                item.put("nationalityName", StringUtils.isEmpty(visitor.getNationalityName()) ? "" : visitor.getNationalityName());
+                // 证件类型
+                item.put("credentialType", DictFrameworkUtils.getDictDataLabel(DictTypeConstants.VISITOR_CREDENTIAL_TYPE, visitor.getCredentialType()));
+                // 证件号
+                item.put("credentialNo", StringUtils.isEmpty(visitor.getCredentialNo()) ? "" : visitor.getCredentialNo());
+                // 出生年月
+                item.put("birthday", StringUtils.isEmpty(visitor.getBirthday()) ? "" : visitor.getBirthday());
+                // 备注
+                item.put("remark", StringUtils.isEmpty(visitor.getRemark()) ? "" : visitor.getRemark());
+
+                touristData.add(item);
+            }
+        }
+
+        // 6. 填充数据
+        excelWriter.fill(new FillWrapper("visitor", touristData),fillConfig, writeSheet);
+        excelWriter.fill(baseData, writeSheet);
+        excelWriter.finish();
+
+        return new File(tmpFile);
+    }
+
 }

+ 1 - 1
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/smsSendconfig/MessageSendServiceImpl.java

@@ -87,7 +87,7 @@ public class MessageSendServiceImpl implements MessageSendService {
                 map.put("routeName", smsSendconfigQueryRespVO.getRouteName());
                 map.put("boatName", smsSendconfigQueryRespVO.getShipName());
                 map.put("startTime", smsSendconfigQueryRespVO.getStartTime());
-                Date lastDate = DateUtil.offsetDay(DateUtil.parse(smsSendconfigQueryRespVO.getStartTime()), -7);
+                Date lastDate = DateUtil.offsetDay(DateUtil.parse(smsSendconfigQueryRespVO.getStartTime()), -4);
                 map.put("lastTime", DateUtil.format(lastDate, "yyyy-MM-dd"));
                 NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO();
                 reqDTO.setTemplateParams(map);

+ 154 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/utils/excel/ExcelStyleHandler.java

@@ -0,0 +1,154 @@
+package com.yc.ship.module.trade.utils.excel;
+
+import com.alibaba.excel.write.handler.CellWriteHandler;
+import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ExcelStyleHandler implements CellWriteHandler {
+    private final int templateRowIndex;
+    private final Map<Integer, CellStyle> templateStyles = new HashMap<>();
+
+    // 保存模板行的合并信息:列索引 -> [起始列, 结束列]
+    private final Map<Integer, int[]> templateMergeInfo = new HashMap<>();
+
+    private boolean templateProcessed = false;
+
+    public ExcelStyleHandler(int templateRowIndex) {
+        this.templateRowIndex = templateRowIndex;
+    }
+
+    @Override
+    public void afterCellDispose(CellWriteHandlerContext context) {
+        if (Boolean.TRUE.equals(context.getHead())) {
+            return;
+        }
+
+        Cell cell = context.getCell();
+        Row currentRow = cell.getRow();
+        int currentRowIndex = currentRow.getRowNum();
+        int colIndex = cell.getColumnIndex();
+        Sheet sheet = context.getWriteSheetHolder().getSheet();
+        Workbook workbook = sheet.getWorkbook();
+
+        // 处理模板行:保存样式和合并信息
+        if (currentRowIndex == templateRowIndex) {
+            if (!templateProcessed) {
+                // 保存样式
+                saveTemplateStyles(currentRow, workbook);
+
+                // 保存合并信息
+                saveTemplateMergeInfo(sheet);
+
+                templateProcessed = true;
+            }
+            return;
+        }
+
+        // 跳过模板行之前的行
+        if (currentRowIndex < templateRowIndex) {
+            return;
+        }
+
+        // ===== 为所有单元格设置样式(包括合并区域内的)=====
+       // CellStyle newStyle = workbook.createCellStyle();
+
+// 应用样式
+        if (templateStyles.containsKey(colIndex)) {
+            //newStyle.cloneStyleFrom(templateStyles.get(colIndex));
+
+            cell.setCellStyle(templateStyles.get(colIndex));
+        }
+
+
+        // 如果这个列在合并区域内,设置边框
+        /*if (templateMergeInfo.containsKey(colIndex)) {
+            int[] range = templateMergeInfo.get(colIndex);
+            int firstCol = range[0];
+            int lastCol = range[1];
+
+            // 根据在合并区域中的位置设置边框
+            setMergeCellBorders(newStyle, colIndex, firstCol, lastCol);
+        }*/
+
+       // cell.setCellStyle(newStyle);
+
+        // 应用合并(只处理合并区域的第一个列)
+        if (templateMergeInfo.containsKey(colIndex)) {
+            int[] range = templateMergeInfo.get(colIndex);
+            int firstCol = range[0];
+            int lastCol = range[1];
+
+            // 只在当前列是合并区域的第一个列时创建合并
+            if (colIndex == firstCol) {
+                CellRangeAddress cra = new CellRangeAddress(
+                        currentRowIndex, currentRowIndex, firstCol, lastCol
+                );
+                sheet.addMergedRegion(cra);
+
+                // 为合并区域设置完整边框
+                setMergeCellBorders(sheet.getColumnStyle(colIndex), colIndex, firstCol, lastCol);
+
+            }
+
+        }
+
+
+
+
+    }
+
+
+    /**
+     * 为合并区域的单元格设置边框
+     * @param style 单元格样式
+     * @param colIndex 当前列索引
+     * @param firstCol 合并区域起始列
+     * @param lastCol 合并区域结束列
+     */
+    private void setMergeCellBorders(CellStyle style,  int colIndex, int firstCol, int lastCol) {
+        // 设置所有边框为细线
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+
+        // 如果有特殊需求,可以根据位置设置不同边框:
+        // - 合并区域的第一个单元格:左、上、下边框
+        // - 合并区域的最后一个单元格:右、上、下边框
+        // - 中间的单元格:上、下边框
+    }
+
+    /**
+     * 保存模板行的合并信息
+     */
+    private void saveTemplateMergeInfo(Sheet sheet) {
+        List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
+        for (CellRangeAddress cra : mergedRegions) {
+            // 只处理模板行上的横向合并
+            if (cra.getFirstRow() == templateRowIndex && cra.getLastRow() == templateRowIndex) {
+                int firstCol = cra.getFirstColumn();
+                int lastCol = cra.getLastColumn();
+
+                // 记录这个合并区域涉及的所有列
+                for (int col = firstCol; col <= lastCol; col++) {
+                    templateMergeInfo.put(col, new int[]{firstCol, lastCol});
+                }
+            }
+        }
+    }
+
+    private void saveTemplateStyles(Row templateRow, Workbook workbook) {
+        for (Cell cell : templateRow) {
+            if (cell != null && cell.getCellStyle() != null) {
+                CellStyle newStyle = workbook.createCellStyle();
+                newStyle.cloneStyleFrom(cell.getCellStyle());
+                templateStyles.put(cell.getColumnIndex(), newStyle);
+            }
+        }
+    }
+}

+ 85 - 5
ship-module-trade/ship-module-trade-biz/src/main/resources/mapper/order/TradeOrderMapper.xml

@@ -1039,7 +1039,6 @@
         o.item_id,
         o.payment_date,
         o.remark,
-        o.route_plan_id,
         o.seller_id,
         o.sell_method,
         o.share_name,
@@ -1048,7 +1047,6 @@
         o.store_id,
         o.store_name,
         o.visitor_type,
-        ps.cost_price,
         tou.contact_name,
         tou.credential_no,
         tou.mobile,
@@ -1076,15 +1074,14 @@
         LEFT JOIN trade_refund_detail trd ON trd.trade_detail_id = td.id
         AND trd.refund_status = 6
         INNER JOIN trade_order_user tou ON o.id = tou.order_id
-        INNER JOIN product_spu ps ON ps.id = td.product_id
         LEFT JOIN trade_invoice_detail i ON i.order_no = o.order_no
         LEFT JOIN trade_invoice ii ON i.invoice_id = ii.id AND ii.invoice_status IN (1,3)
         LEFT JOIN (select order_id,payment_type from trade_order_pay where pay_status=1 GROUP BY order_id) op ON op.order_id = o.id
         LEFT JOIN ota_bill_order obo ON obo.order_id = o.id
         LEFT JOIN ota_bill_store obs ON obs.id = obo.bill_store_id AND obs.bill_status=1
-        where td.validity_end_date >= DATE_SUB(NOW(), INTERVAL #{canInvoicedDay} DAY)
+        where td.use_date >= DATE_SUB(NOW(), INTERVAL #{canInvoicedDay} DAY)
         and o.is_invoice in (0,2)
-        and o.order_status in (7,8,9,11,12)
+        and o.order_status in (6,7,8,9,11,12)
         <if test="vo.orderNo != null and vo.orderNo != ''">
             AND o.order_no = #{vo.orderNo}
         </if>
@@ -2090,4 +2087,87 @@
         GROUP BY rrm.short_name,tv.floor
         ) p
     </select>
+
+
+
+    <select id="selectTotalByOrderIds" resultType="com.yc.ship.module.trade.controller.admin.order.vo.order.OrderTotalRespVO">
+        select sum(adult_total_num) adultTotalNum, sum(child_total_num) childTotalNum, sum(baby_total_num) babyTotalNum,
+        sum(with_total_num) withTotalNum, sum(leader_total_num) leaderTotalNum, sum(free_num) freeNum,
+        sum(order_money) orderMoney, sum(real_money) realMoney,  sum(other_money) otherMoney,
+        sum(adjust_total_money) adjustTotalMoney,  sum(with_amount) withTotalNumMoney,
+        sum(leader_amount) leaderTotalMoney, sum(free_amount) freeAmount, sum(service_money) serviceMoney,
+        sum(up_floor_total_num) upFloorTotalNum, sum(up_floor_total_money) upFloorTotalMoney,
+        sum(plus_total_num) plusTotalNum, sum(collection_service_money) collectionServiceMoney,
+        sum(use_room_total_num) totalRoomNum,sum(free_amount) freeAmount   from trade_order_total
+        where 1=1
+        AND old_order_id in
+        <foreach collection="orderIds" item="item" separator=","  open="(" close=")">
+            #{item}
+        </foreach>
+    </select>
+
+
+    <!-- 查询游客名单导出基础信息(船名、航期、航向) -->
+    <select id="selectTouristExportBase" resultType="java.util.Map">
+        SELECT
+        rs.name as shipName,
+        pv.start_time as travelDate,
+        rr.direction as direction
+        FROM trade_order tor
+        LEFT JOIN product_voyage pv ON tor.voyage_id = pv.id
+        LEFT JOIN resource_ship rs ON pv.ship_id = rs.id
+        LEFT JOIN resource_route rr ON pv.route_id = rr.id
+        LEFT JOIN ota_distributor od on od.id = tor.source_id
+        WHERE tor.deleted = 0
+        <if test="vo.orderNo != null and vo.orderNo != ''">
+                AND tor.order_no = #{vo.orderNo}
+        </if>
+        <if test="vo.voyageId != null and vo.voyageId != ''">
+            AND tor.voyage_id = #{vo.voyageId}
+        </if>
+        <if test="vo.shipId != null and vo.shipId != ''">
+            AND pv.ship_id = #{vo.shipId}
+        </if>
+        <if test="vo.routeId != null and vo.routeId != ''">
+            AND pv.route_id = #{vo.routeId}
+        </if>
+        <if test="vo.travelDateStart != null and vo.travelDateStart != ''">
+            AND pv.start_time &gt;= #{vo.travelDateStart}
+        </if>
+        <if test="vo.travelDateEnd != null and vo.travelDateEnd != ''">
+            AND pv.start_time &lt;= #{vo.travelDateEnd}
+        </if>
+        <if test="vo.orderDateStart != null and vo.orderDateStart != ''">
+            AND tor.create_time &gt;= #{vo.orderDateStart}
+        </if>
+        <if test="vo.orderDateEnd != null and vo.orderDateEnd != ''">
+            AND tor.create_time &lt;= #{vo.orderDateEnd}
+        </if>
+        <if test="vo.orderStatus != null and vo.orderStatus.size() > 0">
+            AND tor.order_status IN
+            <foreach collection="vo.orderStatus" item="item" separator="," open="(" close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="vo.otaId != null and vo.otaId != ''">
+            AND tor.source_id = #{vo.otaId}
+        </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.contactName != null and vo.contactName != ''">
+            AND tor.contact_name LIKE CONCAT('%', #{vo.contactName}, '%')
+        </if>
+        <if test="vo.mobile != null and vo.mobile != ''">
+            AND tor.mobile = #{vo.mobile}
+        </if>
+        LIMIT 1
+    </select>
 </mapper>
+

+ 85 - 1
ship-module-trade/ship-module-trade-biz/src/main/resources/mapper/order/TradeVisitorMapper.xml

@@ -217,7 +217,9 @@
     </select>
 
     <select id="getExportVisitorList" resultType="com.yc.ship.module.trade.controller.admin.order.vo.order.TradeOrderRespExcelVO">
-        select t1.order_no orderNo,t1.group_no groupNo,t1.order_status orderStatus,t1.source_name sourceName,t3.name name,t3.gender gender,t3.credential_no credentialNo,t7.name nationality,t3.birthday birthday,t3.mobile mobile,t3.age age,t3.mobile mobile,t5.short_name roomModelName,t3.floor floor,t6.room_num roomName,t2.price price,t3.remark remark
+        select t1.order_no orderNo,t1.group_no groupNo,t1.order_status orderStatus,t1.source_name sourceName,t3.name name,
+        t3.gender gender,t3.type visitorType,t3.credential_type credentialType,t3.credential_no credentialNo,
+        t7.name nationality,t3.birthday birthday,t3.mobile mobile,t3.age age,t3.mobile mobile,t5.short_name roomModelName,t3.floor floor,t6.room_num roomName,t2.price price,t3.remark remark
         from trade_order t1 inner join trade_detail t2 on t1.id=t2.order_id and t2.product_type = 0 and t2.deleted = 0
         inner join trade_visitor t3 on t2.visitor_id=t3.id and t3.deleted =0
         left join trade_order_room_model t4 on t3.room_index_id=t4.room_index_id and t4.deleted=0
@@ -241,4 +243,86 @@
             </foreach>
         </if>
     </select>
+
+
+    <!-- 查询游客名单导出游客列表 -->
+    <select id="selectTouristExportVisitor" resultType="com.yc.ship.module.trade.controller.admin.order.vo.order.TouristExportVisitorVO">
+        SELECT
+        tv.name,
+        a.name as nationalityName,
+        tv.credential_type as credentialType,
+        tv.credential_no as credentialNo,
+        tv.birthday,
+        tor.remark
+        FROM trade_visitor tv
+        INNER JOIN trade_order tor ON tv.order_id = tor.id AND tor.deleted = 0
+        INNER JOIN trade_detail td ON tv.detail_id = td.id AND td.deleted = 0 AND td.product_type = 0
+        LEFT JOIN area a ON tv.nationality = a.id
+        LEFT JOIN product_voyage pv ON tor.voyage_id = pv.id
+        LEFT JOIN ota_distributor od on od.id = tor.source_id
+        LEFT JOIN trade_order_room_model torm ON tv.room_index_id = torm.room_index_id AND torm.deleted = 0
+        WHERE tv.deleted = 0
+
+            <if test="vo.orderNo != null and vo.orderNo != ''">
+                AND tor.order_no = #{vo.orderNo}
+            </if>
+        <if test="vo.voyageId != null and vo.voyageId != ''">
+            AND tor.voyage_id = #{vo.voyageId}
+        </if>
+        <if test="vo.shipId != null and vo.shipId != ''">
+            AND pv.ship_id = #{vo.shipId}
+        </if>
+        <if test="vo.routeId != null and vo.routeId != ''">
+            AND pv.route_id = #{vo.routeId}
+        </if>
+        <if test="vo.travelDateStart != null and vo.travelDateStart != ''">
+            AND pv.start_time &gt;= #{vo.travelDateStart}
+        </if>
+        <if test="vo.travelDateEnd != null and vo.travelDateEnd != ''">
+            AND pv.start_time &lt;= #{vo.travelDateEnd}
+        </if>
+        <if test="vo.orderDateStart != null and vo.orderDateStart != ''">
+            AND tor.create_time &gt;= #{vo.orderDateStart}
+        </if>
+        <if test="vo.orderDateEnd != null and vo.orderDateEnd != ''">
+            AND tor.create_time &lt;= #{vo.orderDateEnd}
+        </if>
+        <if test="vo.orderStatus != null and vo.orderStatus.size() > 0">
+            AND tor.order_status IN
+            <foreach collection="vo.orderStatus" item="item" separator="," open="(" close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="vo.userName != null and vo.userName != ''">
+            AND tv.name LIKE CONCAT('%', #{vo.userName}, '%')
+        </if>
+        <if test="vo.credentialNo != null and vo.credentialNo != ''">
+            AND tv.credential_no = #{vo.credentialNo}
+        </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 tv.floor = #{vo.floor}
+        </if>
+        <if test="vo.otaId != null and vo.otaId != ''">
+            AND tor.source_id = #{vo.otaId}
+        </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.contactName != null and vo.contactName != ''">
+            AND tor.contact_name LIKE CONCAT('%', #{vo.contactName}, '%')
+        </if>
+        <if test="vo.mobile != null and vo.mobile != ''">
+            AND tor.mobile = #{vo.mobile}
+        </if>
+        ORDER BY tor.order_no ASC, tv.id ASC
+    </select>
 </mapper>

BIN
ship-module-trade/ship-module-trade-biz/src/main/resources/templates/tourist_template.xlsx