|
|
@@ -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);
|