Parcourir la source

Merge branch 'main' of http://47.98.207.247:3000/lsq/ship-ota-server

lishiqiang il y a 1 semaine
Parent
commit
a65ca61099

+ 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("客容量")
     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;
 
-    @Schema(description = "载客率", example = "84.0%")
-    @ExcelProperty("载客率")
+    @Schema(description = "购票载客率", example = "420")
+    @ExcelProperty("购票载客率")
+    private String ticketRate;
+
+    @Schema(description = "床位载客率", example = "84.0%")
+    @ExcelProperty("床位载客率")
     private String passengerRate;
 
     @Schema(description = "房总数", example = "200")
@@ -89,12 +101,21 @@ public class CruiseOpsDailyRespVO {
     @ExcelProperty("客容量同比%")
     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;
 
-    @Schema(description = "载客率同比(百分点)", example = "+2.5")
-    @ExcelProperty("载客率同比")
+    @Schema(description = "购票载客率同比(百分点)", example = "+2.5")
+    @ExcelProperty("购票载客率同比")
+    private String ticketRateYoy;
+    @Schema(description = "床位载客率同比(百分点)", example = "+2.5")
+    @ExcelProperty("床位载客率同比")
     private String passengerRateYoy;
 
     @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;
 
 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.CruiseOpsDailyRespVO;
 import org.apache.ibatis.annotations.Mapper;
@@ -21,6 +22,7 @@ public interface OpsDailyMapper extends BaseMapperX<CruiseOpsDailyRespVO> {
      * @param vo 查询条件
      * @return 数据列表
      */
+    @TenantIgnore
     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.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -52,7 +53,9 @@ public class OpsDailyServiceImpl implements OpsDailyService {
     @Override
     public List<CruiseOpsDailyRespVO> getCruiseOpsDailyList(CruiseOpsDailyReqVO reqVO) {
         // 1. 查询本期原始数据
+        log.info("查询CruiseOpsDailyList任务开始时间{}", LocalDateTime.now());
         List<CruiseOpsDailyRespVO> currentDataList = cruiseOpsDailyMapper.selectCruiseOpsDailyList(reqVO);
+        log.info("查询CruiseOpsDailyList任务结束时间{}", LocalDateTime.now());
         if (CollUtil.isEmpty(currentDataList)) {
             return new ArrayList<>();
         }
@@ -131,13 +134,39 @@ public class OpsDailyServiceImpl implements OpsDailyService {
      * 构建导出表头(与前端页面15列一一对应)
      */
     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;
     }
 
@@ -161,7 +190,10 @@ public class OpsDailyServiceImpl implements OpsDailyService {
                 rowData.add("");    // 航线 - 合并
                 rowData.add("同比");
                 rowData.add(formatYoyForExport(row.getPassengerCapacityYoy()));
+                rowData.add(formatYoyForExport(row.getTicketCountYoy()));
+                rowData.add(formatYoyForExport(row.getFreeCountYoy()));
                 rowData.add(formatYoyForExport(row.getPassengerCountYoy()));
+                rowData.add(formatYoyForExport(row.getTicketRateYoy()));
                 rowData.add(formatYoyForExport(row.getPassengerRateYoy()));
                 rowData.add(formatYoyForExport(row.getTotalRoomsYoy()));
                 rowData.add(formatYoyForExport(row.getUsedRoomsYoy()));
@@ -178,7 +210,10 @@ public class OpsDailyServiceImpl implements OpsDailyService {
                 rowData.add(row.getRoute() != null ? row.getRoute() : "");
                 rowData.add(row.getVoyageNo() != null ? row.getVoyageNo() : "");
                 rowData.add(formatNumber(row.getPassengerCapacity()));
+                rowData.add(formatNumber(row.getTicketCount()));
+                rowData.add(formatNumber(row.getFreeCount()));
                 rowData.add(formatNumber(row.getPassengerCount()));
+                rowData.add(row.getTicketRate() != null ? row.getTicketRate() : "");
                 rowData.add(row.getPassengerRate() != null ? row.getPassengerRate() : "");
                 rowData.add(formatNumber(row.getTotalRooms()));
                 rowData.add(row.getUsedRooms() != null ? row.getUsedRooms() : "");
@@ -242,17 +277,20 @@ public class OpsDailyServiceImpl implements OpsDailyService {
     private void calculateDerivedFields(List<CruiseOpsDailyRespVO> dataList) {
         for (CruiseOpsDailyRespVO item : dataList) {
             // 载客率 = 载客量 / 客容量 * 100
+            // 购票载客率 = 购票 / 客容量 * 100
             if (item.getPassengerCapacity() != null && item.getPassengerCapacity() > 0
                     && item.getPassengerCount() != null) {
                 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
             if (item.getTotalRooms() != null && item.getTotalRooms() > 0
                     && item.getUsedRooms() != null) {
-                double usedRoomsVal = safeParseInt(item.getUsedRooms());
+                double usedRoomsVal = safeParseDouble(item.getUsedRooms());
                 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;
@@ -384,22 +422,28 @@ public class OpsDailyServiceImpl implements OpsDailyService {
 
         // 数值汇总
         int passengerCapacitySum = 0;
+        int ticketCountSum = 0;
+        int freeCountSum = 0;
         int passengerCountSum = 0;
         int totalRoomsSum = 0;
-        int usedRoomsSum = 0;
+        double usedRoomsSum = 0;
         BigDecimal ticketIncomeSum = BigDecimal.ZERO;
         BigDecimal secondIncomeSum = BigDecimal.ZERO;
 
         for (CruiseOpsDailyRespVO item : items) {
             passengerCapacitySum += safeInt(item.getPassengerCapacity());
+            ticketCountSum += safeInt(item.getTicketCount());
+            freeCountSum += safeInt(item.getFreeCount());
             passengerCountSum += safeInt(item.getPassengerCount());
             totalRoomsSum += safeInt(item.getTotalRooms());
-            usedRoomsSum += safeParseInt(item.getUsedRooms());
+            usedRoomsSum += safeParseDouble(item.getUsedRooms());
             ticketIncomeSum = ticketIncomeSum.add(safeBigDecimal(item.getTicketIncome()));
             secondIncomeSum = secondIncomeSum.add(safeBigDecimal(item.getSecondIncome()));
         }
 
         row.setPassengerCapacity(passengerCapacitySum);
+        row.setTicketCount(ticketCountSum);
+        row.setFreeCount(freeCountSum);
         row.setPassengerCount(passengerCountSum);
         row.setTotalRooms(totalRoomsSum);
         row.setUsedRooms(String.valueOf(usedRoomsSum));
@@ -409,11 +453,13 @@ public class OpsDailyServiceImpl implements OpsDailyService {
         // 派生字段重新计算
         if (passengerCapacitySum > 0) {
             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) {
             double rate = (double) usedRoomsSum / totalRoomsSum * 100;
-            row.setRoomRate(String.format("%.1f%%", rate));
+            row.setRoomRate(String.format("%.2f%%", rate));
         }
         row.setTotalIncome(ticketIncomeSum.add(secondIncomeSum));
 
@@ -438,16 +484,21 @@ public class OpsDailyServiceImpl implements OpsDailyService {
         // ===== 计算各指标的同比率 =====
         yoyRow.setPassengerCapacityYoy(calcYoyPercent(
                 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(
                 safeInt(currentRow.getPassengerCount()), safeInt(lastYearRow.getPassengerCount())));
 
         // 载客率同比(百分点差异)
+        yoyRow.setTicketRateYoy(calcRateDiff(currentRow.getTicketRate(), lastYearRow.getTicketRate()));
         yoyRow.setPassengerRateYoy(calcRateDiff(currentRow.getPassengerRate(), lastYearRow.getPassengerRate()));
 
         yoyRow.setTotalRoomsYoy(calcYoyPercent(
                 safeInt(currentRow.getTotalRooms()), safeInt(lastYearRow.getTotalRooms())));
         yoyRow.setUsedRoomsYoy(calcYoyPercent(
-                safeParseInt(currentRow.getUsedRooms()), safeParseInt(lastYearRow.getUsedRooms())));
+                safeParseDouble(currentRow.getUsedRooms()), safeParseDouble(lastYearRow.getUsedRooms())));
 
         // 用房率同比(百分点差异)
         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) {
         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 {
 
-    private static final int TOTAL_COLUMNS = 15;
+    private static final int TOTAL_COLUMNS = 18;
 
     private final List<CruiseOpsDailyRespVO> dataList;
 
@@ -54,7 +54,7 @@ public class CruiseOpsDailyExportStyleHandler implements CellWriteHandler {
             boolean isCumulative = Boolean.TRUE.equals(row.getIsCumulative());
             boolean isYoy = "同比".equals(row.getVoyageNo());
 
-            int excelRowIndex = i + 1; // +1 因为第0行是表头
+            int excelRowIndex = i + 2; // +1 因为第0行是表头
 
             if (isSubtotal && !isYoy) {
                 // 小计数据行 + 紧随的同比行都标记为小计行
@@ -88,7 +88,7 @@ public class CruiseOpsDailyExportStyleHandler implements CellWriteHandler {
 
         Cell cell = context.getCell();
         int excelRowIndex = cell.getRow().getRowNum();
-        int dataRowIndex = excelRowIndex - 1; // 减去表头行
+        int dataRowIndex = excelRowIndex - 2; // 减去表头行
 
         if (dataRowIndex < 0 || dataRowIndex >= dataList.size()) {
             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"
             resultType="com.yc.ship.module.trade.controller.admin.report.vo.CruiseOpsDailyRespVO">
         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,
         r.name AS route,
         v.name AS voyageNo,
         s.capacity AS passengerCapacity,
         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(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
         INNER JOIN resource_ship s
         ON v.ship_id = s.id AND s.deleted = 0
@@ -41,12 +43,24 @@
         GROUP BY order_id
         ) tv ON o.id = tv.order_id
         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
         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
-        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)
         GROUP BY o.id
         ) inc ON o.id = inc.order_id
@@ -56,6 +70,11 @@
         WHERE deleted = 0
         GROUP BY 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
           <if test="startDate != null and startDate != ''">
               AND v.start_time &gt;= #{startDate}