Parcourir la source

增加合计功能

jincheng il y a 1 semaine
Parent
commit
c6e18c26c2

+ 2 - 2
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/report/vo/YangtzePassengerSummaryPageReqVO.java

@@ -22,8 +22,8 @@ public class YangtzePassengerSummaryPageReqVO extends PageParam {
     @Schema(description = "航次ID列表(支持多选)", example = "[1,2,3]")
     private List<Long> voyageIds;
 
-    @Schema(description = "游轮ID", example = "1")
-    private Long shipId;
+    @Schema(description = "游轮ID列表(支持多选)", example = "[1,2,3]")
+    private List<Long> shipIds;
 
     @Schema(description = "开始日期", example = "2026-01-01")
     private String startDate;

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

@@ -633,6 +633,10 @@ public class OpsDailyServiceImpl implements OpsDailyService {
         // 转换数据
         List<List<Object>> exportData = transformExportData2(dataList);
 
+        // 追加合计行
+        List<Object> summaryRow = buildSummaryRow2(dataList);
+        exportData.add(summaryRow);
+
         // 先设置响应头
         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
         response.addHeader("Content-Disposition",
@@ -823,8 +827,95 @@ public class OpsDailyServiceImpl implements OpsDailyService {
     }
 
     /**
-     * 格式化金额为 BigDecimal(保留2位小数),直接输出数字类型避免 Excel 文本格式
+     * 构建合计行(用于导出Excel末尾)
      */
+    private List<Object> buildSummaryRow2(List<YangtzePassengerSummaryRespVO> dataList) {
+        List<Object> row = new ArrayList<>(30);
+        // 序号、船舶、航次、倒计时 — 合计行留空或标注
+        row.add("");
+        row.add("");
+        row.add("合计");
+        row.add("");
+        // 预订间数 - 汇总
+        row.add(sumBigDecimal(dataList, YangtzePassengerSummaryRespVO::getTotalRooms));
+        row.add(sumBigDecimal(dataList, YangtzePassengerSummaryRespVO::getPaidRooms));
+        row.add(sumBigDecimal(dataList, YangtzePassengerSummaryRespVO::getReservedRooms));
+        // 实收人数 - 汇总
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getTotalPassengers));
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getTicketedPassengers));
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getFreePassengers));
+        // 预计收客人数 - 汇总
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getEstimatedPassengers));
+        // 备注 - 留空
+        row.add("");
+        // 财务情况 - 汇总
+        BigDecimal totalReceivable = sumBigDecimal(dataList, YangtzePassengerSummaryRespVO::getReceivableAmount);
+        BigDecimal totalReceived = sumBigDecimal(dataList, YangtzePassengerSummaryRespVO::getReceivedAmount);
+        BigDecimal totalUnreceived = sumBigDecimal(dataList, YangtzePassengerSummaryRespVO::getUnreceivedAmount);
+        row.add(formatMoney(totalReceivable));
+        row.add(formatMoney(totalReceived));
+        row.add(formatMoney(totalUnreceived));
+        // 均价 = 总应收 / 总购票人数
+        int totalTicketed = sumInt(dataList, YangtzePassengerSummaryRespVO::getTicketedPassengers);
+        if (totalTicketed > 0) {
+            row.add(formatMoney(totalReceivable.divide(BigDecimal.valueOf(totalTicketed), 2, RoundingMode.HALF_UP)));
+        } else {
+            row.add(formatMoney(BigDecimal.ZERO));
+        }
+        // 床位载客率 - 客容量汇总,载客率 = 总实收人数 / 总客容量
+        int totalCapacity = sumInt(dataList, YangtzePassengerSummaryRespVO::getCapacity);
+        int totalPassengers = sumInt(dataList, YangtzePassengerSummaryRespVO::getTotalPassengers);
+        row.add(totalCapacity);
+        if (totalCapacity > 0) {
+            double rate = (double) totalPassengers / totalCapacity * 100;
+            row.add(String.format("%.1f%%", rate));
+        } else {
+            row.add("-");
+        }
+        // 实收详情 - 汇总
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getAdultCount));
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getChildCount));
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getInfantCount));
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getCompanionLeaderCount));
+        // 团队情况 - 汇总
+        int totalGroup = sumInt(dataList, YangtzePassengerSummaryRespVO::getGroupCount);
+        int totalIndividual = sumInt(dataList, YangtzePassengerSummaryRespVO::getIndividualCount);
+        row.add(totalGroup);
+        row.add(totalIndividual);
+        row.add(calcRatio(totalGroup, totalIndividual));
+        int totalDomestic = sumInt(dataList, YangtzePassengerSummaryRespVO::getDomesticCount);
+        int totalOverseas = sumInt(dataList, YangtzePassengerSummaryRespVO::getOverseasCount);
+        row.add(totalDomestic);
+        row.add(totalOverseas);
+        row.add(calcRatio(totalDomestic, totalOverseas));
+        // 升楼层礼遇、套房95折 - 汇总
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getUpgradeFloorCount));
+        row.add(sumInt(dataList, YangtzePassengerSummaryRespVO::getSuiteDiscountCount));
+        return row;
+    }
+
+    /**
+     * 求和 - Integer 字段
+     */
+    private int sumInt(List<YangtzePassengerSummaryRespVO> dataList,
+                       java.util.function.Function<YangtzePassengerSummaryRespVO, Integer> getter) {
+        return dataList.stream()
+                .map(getter)
+                .filter(java.util.Objects::nonNull)
+                .mapToInt(Integer::intValue)
+                .sum();
+    }
+
+    /**
+     * 求和 - BigDecimal 字段
+     */
+    private BigDecimal sumBigDecimal(List<YangtzePassengerSummaryRespVO> dataList,
+                                     java.util.function.Function<YangtzePassengerSummaryRespVO, BigDecimal> getter) {
+        return dataList.stream()
+                .map(getter)
+                .filter(java.util.Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
     private BigDecimal formatMoney(BigDecimal amount) {
         if (amount == null) return BigDecimal.ZERO;
         return amount.setScale(2, RoundingMode.HALF_UP);

+ 5 - 2
ship-module-trade/ship-module-trade-biz/src/main/resources/mapper/report/YangtzePassengerSummaryMapper.xml

@@ -164,8 +164,11 @@
                 #{id}
             </foreach>
         </if>
-        <if test="vo.shipId != null">
-            AND v.ship_id = #{vo.shipId}
+        <if test="vo.shipIds != null and vo.shipIds.size() > 0">
+            AND v.ship_id IN
+            <foreach collection="vo.shipIds" item="shipId" open="(" separator="," close=")">
+                #{shipId}
+            </foreach>
         </if>
         <if test="vo.startDate != null and vo.startDate != ''">
             AND v.start_time &gt;= #{vo.startDate}