Просмотр исходного кода

省际度假游轮经营情况日报表调整

caotao 1 неделя назад
Родитель
Сommit
6d004ecbdc

+ 29 - 8
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/report/vo/CruiseOpsDailyRespVO.java

@@ -48,12 +48,24 @@ public class CruiseOpsDailyRespVO {
     @ExcelProperty("客容量")
     @ExcelProperty("客容量")
     private Integer passengerCapacity;
     private Integer passengerCapacity;
 
 
-    @Schema(description = "载客量", example = "420")
-    @ExcelProperty("载客量")
+    @Schema(description = "购票", example = "420")
+    @ExcelProperty({"载客量", "购票"})
+    private Integer ticketCount;
+
+    @Schema(description = "免票", example = "420")
+    @ExcelProperty({"载客量", "免票"})
+    private Integer freeCount;
+
+    @Schema(description = "合计", example = "420")
+    @ExcelProperty({"载客量", "合计"})
     private Integer passengerCount;
     private Integer passengerCount;
 
 
-    @Schema(description = "载客率", example = "84.0%")
-    @ExcelProperty("载客率")
+    @Schema(description = "购票载客率", example = "420")
+    @ExcelProperty("购票载客率")
+    private String ticketRate;
+
+    @Schema(description = "床位载客率", example = "84.0%")
+    @ExcelProperty("床位载客率")
     private String passengerRate;
     private String passengerRate;
 
 
     @Schema(description = "房总数", example = "200")
     @Schema(description = "房总数", example = "200")
@@ -89,12 +101,21 @@ public class CruiseOpsDailyRespVO {
     @ExcelProperty("客容量同比%")
     @ExcelProperty("客容量同比%")
     private String passengerCapacityYoy;
     private String passengerCapacityYoy;
 
 
-    @Schema(description = "载客量同比率(%)", example = "12.3")
-    @ExcelProperty("载客量同比%")
+    @Schema(description = "购票同比率(%)", example = "12.3")
+    @ExcelProperty("购票同比%")
+    private String ticketCountYoy;
+    @Schema(description = "免票同比率(%)", example = "12.3")
+    @ExcelProperty("免票同比%")
+    private String freeCountYoy;
+    @Schema(description = "合计同比率(%)", example = "12.3")
+    @ExcelProperty("合计同比%")
     private String passengerCountYoy;
     private String passengerCountYoy;
 
 
-    @Schema(description = "载客率同比(百分点)", example = "+2.5")
-    @ExcelProperty("载客率同比")
+    @Schema(description = "购票载客率同比(百分点)", example = "+2.5")
+    @ExcelProperty("购票载客率同比")
+    private String ticketRateYoy;
+    @Schema(description = "床位载客率同比(百分点)", example = "+2.5")
+    @ExcelProperty("床位载客率同比")
     private String passengerRateYoy;
     private String passengerRateYoy;
 
 
     @Schema(description = "房总数同比率(%)", example = "0.0")
     @Schema(description = "房总数同比率(%)", example = "0.0")

+ 2 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/mysql/report/OpsDailyMapper.java

@@ -1,6 +1,7 @@
 package com.yc.ship.module.trade.dal.mysql.report;
 package com.yc.ship.module.trade.dal.mysql.report;
 
 
 import com.yc.ship.framework.mybatis.core.mapper.BaseMapperX;
 import com.yc.ship.framework.mybatis.core.mapper.BaseMapperX;
+import com.yc.ship.framework.tenant.core.aop.TenantIgnore;
 import com.yc.ship.module.trade.controller.admin.report.vo.CruiseOpsDailyReqVO;
 import com.yc.ship.module.trade.controller.admin.report.vo.CruiseOpsDailyReqVO;
 import com.yc.ship.module.trade.controller.admin.report.vo.CruiseOpsDailyRespVO;
 import com.yc.ship.module.trade.controller.admin.report.vo.CruiseOpsDailyRespVO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Mapper;
@@ -21,6 +22,7 @@ public interface OpsDailyMapper extends BaseMapperX<CruiseOpsDailyRespVO> {
      * @param vo 查询条件
      * @param vo 查询条件
      * @return 数据列表
      * @return 数据列表
      */
      */
+    @TenantIgnore
     List<CruiseOpsDailyRespVO> selectCruiseOpsDailyList(CruiseOpsDailyReqVO vo);
     List<CruiseOpsDailyRespVO> selectCruiseOpsDailyList(CruiseOpsDailyReqVO vo);
 
 
 }
 }

+ 77 - 15
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/report/impl/OpsDailyServiceImpl.java

@@ -32,6 +32,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.math.RoundingMode;
 import java.net.URLEncoder;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
@@ -52,7 +53,9 @@ public class OpsDailyServiceImpl implements OpsDailyService {
     @Override
     @Override
     public List<CruiseOpsDailyRespVO> getCruiseOpsDailyList(CruiseOpsDailyReqVO reqVO) {
     public List<CruiseOpsDailyRespVO> getCruiseOpsDailyList(CruiseOpsDailyReqVO reqVO) {
         // 1. 查询本期原始数据
         // 1. 查询本期原始数据
+        log.info("查询CruiseOpsDailyList任务开始时间{}", LocalDateTime.now());
         List<CruiseOpsDailyRespVO> currentDataList = cruiseOpsDailyMapper.selectCruiseOpsDailyList(reqVO);
         List<CruiseOpsDailyRespVO> currentDataList = cruiseOpsDailyMapper.selectCruiseOpsDailyList(reqVO);
+        log.info("查询CruiseOpsDailyList任务结束时间{}", LocalDateTime.now());
         if (CollUtil.isEmpty(currentDataList)) {
         if (CollUtil.isEmpty(currentDataList)) {
             return new ArrayList<>();
             return new ArrayList<>();
         }
         }
@@ -131,13 +134,39 @@ public class OpsDailyServiceImpl implements OpsDailyService {
      * 构建导出表头(与前端页面15列一一对应)
      * 构建导出表头(与前端页面15列一一对应)
      */
      */
     private List<List<String>> buildExportHeaders() {
     private List<List<String>> buildExportHeaders() {
-        String[] headers = {"序号", "月份", "日期", "船舶", "航线", "航次号",
-                "客容量", "载客量", "载客率", "房总数", "用房数", "用房率",
-                "船票收入", "二消收入", "收入合计"};
-        List<List<String>> head = new ArrayList<>(headers.length);
-        for (String h : headers) {
-            head.add(Collections.singletonList(h));
-        }
+
+        List<List<String>> head = new ArrayList<>();
+
+        // 一级表头列(无二级表头,只设置一个元素)
+        head.add(new ArrayList<>(Arrays.asList("序号")));
+        head.add(new ArrayList<>(Arrays.asList("月份")));
+        head.add(new ArrayList<>(Arrays.asList("日期")));
+        head.add(new ArrayList<>(Arrays.asList("船舶")));
+        head.add(new ArrayList<>(Arrays.asList("航线")));
+        head.add(new ArrayList<>(Arrays.asList("航次号")));
+
+        // 客容量(无二级表头)
+        head.add(new ArrayList<>(Arrays.asList("客容量")));
+
+        // 乘客统计(二级表头)
+        head.add(new ArrayList<>(Arrays.asList("载客量", "购票")));
+        head.add(new ArrayList<>(Arrays.asList("载客量", "免票")));
+        head.add(new ArrayList<>(Arrays.asList("载客量", "合计")));
+
+        // 载客率(无二级表头)
+        head.add(new ArrayList<>(Arrays.asList("购票载客率")));
+        head.add(new ArrayList<>(Arrays.asList("床位载客率")));
+
+        // 房间统计(无二级表头)
+        head.add(new ArrayList<>(Arrays.asList("房总数")));
+        head.add(new ArrayList<>(Arrays.asList("用房数")));
+        head.add(new ArrayList<>(Arrays.asList("用房率")));
+
+        // 收入统计(无二级表头)
+        head.add(new ArrayList<>(Arrays.asList("船票收入")));
+        head.add(new ArrayList<>(Arrays.asList("二消收入")));
+        head.add(new ArrayList<>(Arrays.asList("收入合计")));
+
         return head;
         return head;
     }
     }
 
 
@@ -161,7 +190,10 @@ public class OpsDailyServiceImpl implements OpsDailyService {
                 rowData.add("");    // 航线 - 合并
                 rowData.add("");    // 航线 - 合并
                 rowData.add("同比");
                 rowData.add("同比");
                 rowData.add(formatYoyForExport(row.getPassengerCapacityYoy()));
                 rowData.add(formatYoyForExport(row.getPassengerCapacityYoy()));
+                rowData.add(formatYoyForExport(row.getTicketCountYoy()));
+                rowData.add(formatYoyForExport(row.getFreeCountYoy()));
                 rowData.add(formatYoyForExport(row.getPassengerCountYoy()));
                 rowData.add(formatYoyForExport(row.getPassengerCountYoy()));
+                rowData.add(formatYoyForExport(row.getTicketRateYoy()));
                 rowData.add(formatYoyForExport(row.getPassengerRateYoy()));
                 rowData.add(formatYoyForExport(row.getPassengerRateYoy()));
                 rowData.add(formatYoyForExport(row.getTotalRoomsYoy()));
                 rowData.add(formatYoyForExport(row.getTotalRoomsYoy()));
                 rowData.add(formatYoyForExport(row.getUsedRoomsYoy()));
                 rowData.add(formatYoyForExport(row.getUsedRoomsYoy()));
@@ -178,7 +210,10 @@ public class OpsDailyServiceImpl implements OpsDailyService {
                 rowData.add(row.getRoute() != null ? row.getRoute() : "");
                 rowData.add(row.getRoute() != null ? row.getRoute() : "");
                 rowData.add(row.getVoyageNo() != null ? row.getVoyageNo() : "");
                 rowData.add(row.getVoyageNo() != null ? row.getVoyageNo() : "");
                 rowData.add(formatNumber(row.getPassengerCapacity()));
                 rowData.add(formatNumber(row.getPassengerCapacity()));
+                rowData.add(formatNumber(row.getTicketCount()));
+                rowData.add(formatNumber(row.getFreeCount()));
                 rowData.add(formatNumber(row.getPassengerCount()));
                 rowData.add(formatNumber(row.getPassengerCount()));
+                rowData.add(row.getTicketRate() != null ? row.getTicketRate() : "");
                 rowData.add(row.getPassengerRate() != null ? row.getPassengerRate() : "");
                 rowData.add(row.getPassengerRate() != null ? row.getPassengerRate() : "");
                 rowData.add(formatNumber(row.getTotalRooms()));
                 rowData.add(formatNumber(row.getTotalRooms()));
                 rowData.add(row.getUsedRooms() != null ? row.getUsedRooms() : "");
                 rowData.add(row.getUsedRooms() != null ? row.getUsedRooms() : "");
@@ -242,17 +277,20 @@ public class OpsDailyServiceImpl implements OpsDailyService {
     private void calculateDerivedFields(List<CruiseOpsDailyRespVO> dataList) {
     private void calculateDerivedFields(List<CruiseOpsDailyRespVO> dataList) {
         for (CruiseOpsDailyRespVO item : dataList) {
         for (CruiseOpsDailyRespVO item : dataList) {
             // 载客率 = 载客量 / 客容量 * 100
             // 载客率 = 载客量 / 客容量 * 100
+            // 购票载客率 = 购票 / 客容量 * 100
             if (item.getPassengerCapacity() != null && item.getPassengerCapacity() > 0
             if (item.getPassengerCapacity() != null && item.getPassengerCapacity() > 0
                     && item.getPassengerCount() != null) {
                     && item.getPassengerCount() != null) {
                 double rate = (double) item.getPassengerCount() / item.getPassengerCapacity() * 100;
                 double rate = (double) item.getPassengerCount() / item.getPassengerCapacity() * 100;
-                item.setPassengerRate(String.format("%.1f%%", rate));
+                item.setPassengerRate(String.format("%.2f%%", rate));
+                double ticketRate = (double) item.getTicketCount() / item.getPassengerCapacity() * 100;
+                item.setTicketRate(String.format("%.2f%%", ticketRate));
             }
             }
             // 用房率 = 用房数 / 房总数 * 100
             // 用房率 = 用房数 / 房总数 * 100
             if (item.getTotalRooms() != null && item.getTotalRooms() > 0
             if (item.getTotalRooms() != null && item.getTotalRooms() > 0
                     && item.getUsedRooms() != null) {
                     && item.getUsedRooms() != null) {
-                double usedRoomsVal = safeParseInt(item.getUsedRooms());
+                double usedRoomsVal = safeParseDouble(item.getUsedRooms());
                 double rate = usedRoomsVal / item.getTotalRooms() * 100;
                 double rate = usedRoomsVal / item.getTotalRooms() * 100;
-                item.setRoomRate(String.format("%.1f%%", rate));
+                item.setRoomRate(String.format("%.2f%%", rate));
             }
             }
             // 收入合计 = 船票收入 + 二消收入
             // 收入合计 = 船票收入 + 二消收入
             BigDecimal ticket = item.getTicketIncome() != null ? item.getTicketIncome() : BigDecimal.ZERO;
             BigDecimal ticket = item.getTicketIncome() != null ? item.getTicketIncome() : BigDecimal.ZERO;
@@ -384,22 +422,28 @@ public class OpsDailyServiceImpl implements OpsDailyService {
 
 
         // 数值汇总
         // 数值汇总
         int passengerCapacitySum = 0;
         int passengerCapacitySum = 0;
+        int ticketCountSum = 0;
+        int freeCountSum = 0;
         int passengerCountSum = 0;
         int passengerCountSum = 0;
         int totalRoomsSum = 0;
         int totalRoomsSum = 0;
-        int usedRoomsSum = 0;
+        double usedRoomsSum = 0;
         BigDecimal ticketIncomeSum = BigDecimal.ZERO;
         BigDecimal ticketIncomeSum = BigDecimal.ZERO;
         BigDecimal secondIncomeSum = BigDecimal.ZERO;
         BigDecimal secondIncomeSum = BigDecimal.ZERO;
 
 
         for (CruiseOpsDailyRespVO item : items) {
         for (CruiseOpsDailyRespVO item : items) {
             passengerCapacitySum += safeInt(item.getPassengerCapacity());
             passengerCapacitySum += safeInt(item.getPassengerCapacity());
+            ticketCountSum += safeInt(item.getTicketCount());
+            freeCountSum += safeInt(item.getFreeCount());
             passengerCountSum += safeInt(item.getPassengerCount());
             passengerCountSum += safeInt(item.getPassengerCount());
             totalRoomsSum += safeInt(item.getTotalRooms());
             totalRoomsSum += safeInt(item.getTotalRooms());
-            usedRoomsSum += safeParseInt(item.getUsedRooms());
+            usedRoomsSum += safeParseDouble(item.getUsedRooms());
             ticketIncomeSum = ticketIncomeSum.add(safeBigDecimal(item.getTicketIncome()));
             ticketIncomeSum = ticketIncomeSum.add(safeBigDecimal(item.getTicketIncome()));
             secondIncomeSum = secondIncomeSum.add(safeBigDecimal(item.getSecondIncome()));
             secondIncomeSum = secondIncomeSum.add(safeBigDecimal(item.getSecondIncome()));
         }
         }
 
 
         row.setPassengerCapacity(passengerCapacitySum);
         row.setPassengerCapacity(passengerCapacitySum);
+        row.setTicketCount(ticketCountSum);
+        row.setFreeCount(freeCountSum);
         row.setPassengerCount(passengerCountSum);
         row.setPassengerCount(passengerCountSum);
         row.setTotalRooms(totalRoomsSum);
         row.setTotalRooms(totalRoomsSum);
         row.setUsedRooms(String.valueOf(usedRoomsSum));
         row.setUsedRooms(String.valueOf(usedRoomsSum));
@@ -409,11 +453,13 @@ public class OpsDailyServiceImpl implements OpsDailyService {
         // 派生字段重新计算
         // 派生字段重新计算
         if (passengerCapacitySum > 0) {
         if (passengerCapacitySum > 0) {
             double rate = (double) passengerCountSum / passengerCapacitySum * 100;
             double rate = (double) passengerCountSum / passengerCapacitySum * 100;
-            row.setPassengerRate(String.format("%.1f%%", rate));
+            row.setPassengerRate(String.format("%.2f%%", rate));
+            double ticketRate = (double) ticketCountSum / passengerCapacitySum * 100;
+            row.setTicketRate(String.format("%.2f%%", ticketRate));
         }
         }
         if (totalRoomsSum > 0) {
         if (totalRoomsSum > 0) {
             double rate = (double) usedRoomsSum / totalRoomsSum * 100;
             double rate = (double) usedRoomsSum / totalRoomsSum * 100;
-            row.setRoomRate(String.format("%.1f%%", rate));
+            row.setRoomRate(String.format("%.2f%%", rate));
         }
         }
         row.setTotalIncome(ticketIncomeSum.add(secondIncomeSum));
         row.setTotalIncome(ticketIncomeSum.add(secondIncomeSum));
 
 
@@ -438,16 +484,21 @@ public class OpsDailyServiceImpl implements OpsDailyService {
         // ===== 计算各指标的同比率 =====
         // ===== 计算各指标的同比率 =====
         yoyRow.setPassengerCapacityYoy(calcYoyPercent(
         yoyRow.setPassengerCapacityYoy(calcYoyPercent(
                 safeInt(currentRow.getPassengerCapacity()), safeInt(lastYearRow.getPassengerCapacity())));
                 safeInt(currentRow.getPassengerCapacity()), safeInt(lastYearRow.getPassengerCapacity())));
+        yoyRow.setTicketCountYoy(calcYoyPercent(
+                safeInt(currentRow.getTicketCount()), safeInt(lastYearRow.getTicketCount())));
+        yoyRow.setFreeCountYoy(calcYoyPercent(
+                safeInt(currentRow.getFreeCount()), safeInt(lastYearRow.getFreeCount())));
         yoyRow.setPassengerCountYoy(calcYoyPercent(
         yoyRow.setPassengerCountYoy(calcYoyPercent(
                 safeInt(currentRow.getPassengerCount()), safeInt(lastYearRow.getPassengerCount())));
                 safeInt(currentRow.getPassengerCount()), safeInt(lastYearRow.getPassengerCount())));
 
 
         // 载客率同比(百分点差异)
         // 载客率同比(百分点差异)
+        yoyRow.setTicketRateYoy(calcRateDiff(currentRow.getTicketRate(), lastYearRow.getTicketRate()));
         yoyRow.setPassengerRateYoy(calcRateDiff(currentRow.getPassengerRate(), lastYearRow.getPassengerRate()));
         yoyRow.setPassengerRateYoy(calcRateDiff(currentRow.getPassengerRate(), lastYearRow.getPassengerRate()));
 
 
         yoyRow.setTotalRoomsYoy(calcYoyPercent(
         yoyRow.setTotalRoomsYoy(calcYoyPercent(
                 safeInt(currentRow.getTotalRooms()), safeInt(lastYearRow.getTotalRooms())));
                 safeInt(currentRow.getTotalRooms()), safeInt(lastYearRow.getTotalRooms())));
         yoyRow.setUsedRoomsYoy(calcYoyPercent(
         yoyRow.setUsedRoomsYoy(calcYoyPercent(
-                safeParseInt(currentRow.getUsedRooms()), safeParseInt(lastYearRow.getUsedRooms())));
+                safeParseDouble(currentRow.getUsedRooms()), safeParseDouble(lastYearRow.getUsedRooms())));
 
 
         // 用房率同比(百分点差异)
         // 用房率同比(百分点差异)
         yoyRow.setRoomRateYoy(calcRateDiff(currentRow.getRoomRate(), lastYearRow.getRoomRate()));
         yoyRow.setRoomRateYoy(calcRateDiff(currentRow.getRoomRate(), lastYearRow.getRoomRate()));
@@ -514,6 +565,17 @@ public class OpsDailyServiceImpl implements OpsDailyService {
         }
         }
     }
     }
 
 
+    private double safeParseDouble(String val) {
+        if (val == null || val.isEmpty()) {
+            return 0.0;
+        }
+        try {
+            return Double.parseDouble(val);
+        } catch (NumberFormatException e) {
+            return 0.0;
+        }
+    }
+
     private BigDecimal safeBigDecimal(BigDecimal val) {
     private BigDecimal safeBigDecimal(BigDecimal val) {
         return val != null ? val : BigDecimal.ZERO;
         return val != null ? val : BigDecimal.ZERO;
     }
     }

+ 3 - 3
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/utils/excel/CruiseOpsDailyExportStyleHandler.java

@@ -17,7 +17,7 @@ import java.util.*;
  */
  */
 public class CruiseOpsDailyExportStyleHandler implements CellWriteHandler {
 public class CruiseOpsDailyExportStyleHandler implements CellWriteHandler {
 
 
-    private static final int TOTAL_COLUMNS = 15;
+    private static final int TOTAL_COLUMNS = 18;
 
 
     private final List<CruiseOpsDailyRespVO> dataList;
     private final List<CruiseOpsDailyRespVO> dataList;
 
 
@@ -54,7 +54,7 @@ public class CruiseOpsDailyExportStyleHandler implements CellWriteHandler {
             boolean isCumulative = Boolean.TRUE.equals(row.getIsCumulative());
             boolean isCumulative = Boolean.TRUE.equals(row.getIsCumulative());
             boolean isYoy = "同比".equals(row.getVoyageNo());
             boolean isYoy = "同比".equals(row.getVoyageNo());
 
 
-            int excelRowIndex = i + 1; // +1 因为第0行是表头
+            int excelRowIndex = i + 2; // +1 因为第0行是表头
 
 
             if (isSubtotal && !isYoy) {
             if (isSubtotal && !isYoy) {
                 // 小计数据行 + 紧随的同比行都标记为小计行
                 // 小计数据行 + 紧随的同比行都标记为小计行
@@ -88,7 +88,7 @@ public class CruiseOpsDailyExportStyleHandler implements CellWriteHandler {
 
 
         Cell cell = context.getCell();
         Cell cell = context.getCell();
         int excelRowIndex = cell.getRow().getRowNum();
         int excelRowIndex = cell.getRow().getRowNum();
-        int dataRowIndex = excelRowIndex - 1; // 减去表头行
+        int dataRowIndex = excelRowIndex - 2; // 减去表头行
 
 
         if (dataRowIndex < 0 || dataRowIndex >= dataList.size()) {
         if (dataRowIndex < 0 || dataRowIndex >= dataList.size()) {
             return;
             return;

+ 26 - 7
ship-module-trade/ship-module-trade-biz/src/main/resources/mapper/report/OpsDailyMapper.xml

@@ -7,17 +7,19 @@
             parameterType="com.yc.ship.module.trade.controller.admin.report.vo.CruiseOpsDailyReqVO"
             parameterType="com.yc.ship.module.trade.controller.admin.report.vo.CruiseOpsDailyReqVO"
             resultType="com.yc.ship.module.trade.controller.admin.report.vo.CruiseOpsDailyRespVO">
             resultType="com.yc.ship.module.trade.controller.admin.report.vo.CruiseOpsDailyRespVO">
         SELECT
         SELECT
-        DATE_FORMAT(v.start_time, '%Y-%m') AS `month`,
-        DATE_FORMAT(v.start_time, '%Y-%m-%d') AS `date`,
+        DATE_FORMAT(v.boarding_time, '%Y-%m') AS `month`,
+        DATE_FORMAT(v.boarding_time, '%Y-%m-%d') AS `date`,
         s.name AS ship,
         s.name AS ship,
         r.name AS route,
         r.name AS route,
         v.name AS voyageNo,
         v.name AS voyageNo,
         s.capacity AS passengerCapacity,
         s.capacity AS passengerCapacity,
         COALESCE(sum(tv.passengerCount), 0) AS passengerCount,
         COALESCE(sum(tv.passengerCount), 0) AS passengerCount,
+        COALESCE(sum(ticket.ticketCount), 0) AS ticketCount,
+        COALESCE(sum(free.freeCount), 0) AS freeCount,
         COALESCE(rr.totalRooms, 0) AS totalRooms,
         COALESCE(rr.totalRooms, 0) AS totalRooms,
         COALESCE(SUM(rm.usedRooms), 0) AS usedRooms,
         COALESCE(SUM(rm.usedRooms), 0) AS usedRooms,
-        COALESCE(inc.ticketIncome, 0) AS ticketIncome,
-        0 AS secondIncome
+        COALESCE(sum(inc.ticketIncome), 0) AS ticketIncome,
+        COALESCE(sum(bmb.secondIncome), 0) AS secondIncome
         FROM product_voyage v
         FROM product_voyage v
         INNER JOIN resource_ship s
         INNER JOIN resource_ship s
         ON v.ship_id = s.id AND s.deleted = 0
         ON v.ship_id = s.id AND s.deleted = 0
@@ -41,12 +43,24 @@
         GROUP BY order_id
         GROUP BY order_id
         ) tv ON o.id = tv.order_id
         ) tv ON o.id = tv.order_id
         LEFT JOIN (
         LEFT JOIN (
+        SELECT t.order_id, COUNT(t.id) AS ticketCount
+        FROM trade_visitor t
+        LEFT JOIN trade_order td on td.id = t.order_id and td.deleted=0
+        WHERE t.deleted = 0 and td.source_id not in ('2039225917977522177', '2041321150626263042', '2042951563081805826')
+        GROUP BY t.order_id
+        ) ticket ON o.id = ticket.order_id
+        LEFT JOIN (
+        SELECT t.order_id, COUNT(t.id) AS freeCount
+        FROM trade_visitor t
+        LEFT JOIN trade_order td on td.id = t.order_id and td.deleted=0
+        WHERE t.deleted = 0 and td.source_id in ('2039225917977522177', '2041321150626263042', '2042951563081805826')
+        GROUP BY t.order_id
+        ) free ON o.id = free.order_id
+        LEFT JOIN (
         SELECT
         SELECT
         o.id AS order_id,
         o.id AS order_id,
-        SUM(CASE WHEN o.pay_status = 1 THEN p.pay_amount ELSE o.real_pay_amount END) AS ticketIncome
+        SUM(o.pay_amount) AS ticketIncome
         FROM trade_order o
         FROM trade_order o
-        LEFT JOIN trade_order_pay p
-        ON o.pay_status = 1 AND p.order_id = o.id AND p.deleted = 0 AND p.pay_status = 1
         WHERE o.deleted = 0 AND o.order_status in (15, 14, 13, 10, 12, 9, 8, 7, 6, 5, 4, 3, 1, 0)
         WHERE o.deleted = 0 AND o.order_status in (15, 14, 13, 10, 12, 9, 8, 7, 6, 5, 4, 3, 1, 0)
         GROUP BY o.id
         GROUP BY o.id
         ) inc ON o.id = inc.order_id
         ) inc ON o.id = inc.order_id
@@ -56,6 +70,11 @@
         WHERE deleted = 0
         WHERE deleted = 0
         GROUP BY ship_id
         GROUP BY ship_id
         ) rr ON v.ship_id = rr.ship_id
         ) rr ON v.ship_id = rr.ship_id
+        LEFT JOIN (
+        SELECT tv.order_id, sum(bmb.pay_amount) AS secondIncome FROM buss_member_bill bmb
+        LEFT JOIN trade_visitor tv ON CAST(tv.id AS CHAR) COLLATE utf8mb4_general_ci = bmb.member_id AND tv.deleted=0 WHERE bmb.deleted = 0
+        GROUP BY tv.order_id
+        ) bmb on bmb.order_id = o.id
         WHERE v.deleted = 0
         WHERE v.deleted = 0
           <if test="startDate != null and startDate != ''">
           <if test="startDate != null and startDate != ''">
               AND v.start_time &gt;= #{startDate}
               AND v.start_time &gt;= #{startDate}