diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java index 0ffbd7612..b951552ee 100644 --- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java +++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java @@ -508,24 +508,53 @@ public class LeaseApplicationService { * 参数与 /warehouseOccupancyRate、/list 一致 */ public void exportOccupancyRate(HttpServletResponse response, ShipperLeaseDetailsDO shipperLeaseDetailsDO) throws IOException { - // ===== 1. 查出租率(注意:该方法内部会修改传入的 DO,所以先查它)===== - List rateList = warehouseOccupancyRate(shipperLeaseDetailsDO); + // 注意:本方法不调用 warehouseOccupancyRate(),因为该方法在不传 warehouseId 时 + // totalArea 会算成全系统所有仓库库区面积之和(如 6168),导致导出面积/日租率错误。 + // 这里自行按 (业务日期 + 仓库) 维度计算,保证多仓库导出时每个仓库的面积/日租率正确。 - // ===== 2. 用副本查明细,避免被上面改过的 DO 影响 ===== + // ===== 1. 查全部明细(用副本 DO,避免影响外部)===== ShipperLeaseDetailsDO detailDO = new ShipperLeaseDetailsDO(); BeanUtils.copyProperties(shipperLeaseDetailsDO, detailDO); List detailList = shipperLeaseDetailsService.queryList(detailDO); - - // ===== 3. 出租率按 (业务日期 + 仓库ID) 建映射,方便明细行查汇总 ===== - SimpleDateFormat keySdf = new SimpleDateFormat("yyyy-MM-dd"); - Map rateMap = new HashMap<>(); - for (WarehouseOccupancyRate r : rateList) { - String key = (r.getBusinessDate() == null ? "" : keySdf.format(r.getBusinessDate())) - + "_" + r.getWarehouseId(); - rateMap.put(key, r); + if (detailList == null) { + detailList = new ArrayList<>(); } - // ===== 4. 明细为主,每行拼上对应仓库当天的汇总 ===== + // ===== 2. 预算每个仓库的总面积(启用库区的 storageRegion 累加),建 warehouseId -> totalArea 映射 ===== + Set warehouseIds = detailList.stream() + .map(ShipperLeaseDetailsPO::getWarehouseId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + Map warehouseTotalAreaMap = new HashMap<>(); + for (Long wid : warehouseIds) { + StorageSectionDO storageSectionDO = new StorageSectionDO(); + storageSectionDO.setWarehouseId(wid); + storageSectionDO.setOpeningUp(1); + List sections = storageSectionApplicationService.queryList(storageSectionDO); + BigDecimal area = BigDecimal.ZERO; + for (StorageSectionPO s : sections) { + area = area.add(s.getStorageRegion() == null ? BigDecimal.ZERO : s.getStorageRegion()); + } + warehouseTotalAreaMap.put(wid, area); + } + + // ===== 3. 按 (业务日期 + 仓库ID) 聚合,算每个仓库当天的整租/散租面积 ===== + // summaryMap: key -> [整租面积, 散租面积] + SimpleDateFormat keySdf = new SimpleDateFormat("yyyy-MM-dd"); + Map summaryMap = new HashMap<>(); + for (ShipperLeaseDetailsPO d : detailList) { + String key = (d.getBusinessDate() == null ? "" : keySdf.format(d.getBusinessDate())) + + "_" + d.getWarehouseId(); + BigDecimal[] arr = summaryMap.computeIfAbsent(key, k -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO}); + BigDecimal leaseArea = d.getLeaseArea() == null ? BigDecimal.ZERO : d.getLeaseArea(); + if ("整租".equals(d.getLeaseType())) { + arr[0] = arr[0].add(leaseArea); + } else { + arr[1] = arr[1].add(leaseArea); + } + } + + // ===== 4. 明细为主,每行拼上对应仓库当天的汇总(总面积/日租率按仓库单独算)===== List exportList = new ArrayList<>(); for (ShipperLeaseDetailsPO d : detailList) { WarehouseLeaseExportVO vo = new WarehouseLeaseExportVO(); @@ -536,20 +565,27 @@ public class LeaseApplicationService { vo.setCargoOwnerName(d.getCargoOwnerName()); vo.setLeaseType(d.getLeaseType()); vo.setLeaseArea(d.getLeaseArea()); - // 汇总列(从映射取,找不到就留空) + // 汇总列 String key = (d.getBusinessDate() == null ? "" : keySdf.format(d.getBusinessDate())) + "_" + d.getWarehouseId(); - WarehouseOccupancyRate r = rateMap.get(key); - if (r != null) { - vo.setEntireLeaseArea(r.getEntireLeaseArea()); - vo.setFractionalLeaseArea(r.getFractionalLeaseArea()); - vo.setTotalArea(r.getTotalArea()); - vo.setDailyRentalRate(r.getDailyRentalRate()); - } + BigDecimal[] arr = summaryMap.get(key); + BigDecimal entireLeaseArea = (arr != null) ? arr[0] : BigDecimal.ZERO; + BigDecimal fractionalLeaseArea = (arr != null) ? arr[1] : BigDecimal.ZERO; + vo.setEntireLeaseArea(entireLeaseArea); + vo.setFractionalLeaseArea(fractionalLeaseArea); + // 该仓库的总面积(按仓库单独算,不再用全局总和) + BigDecimal widTotalArea = warehouseTotalAreaMap.getOrDefault(d.getWarehouseId(), BigDecimal.ZERO); + vo.setTotalArea(widTotalArea); + // 日租率 = (整租+散租) / 总面积 × 100,保留2位小数(直接输出百分比值,如 10.00) + BigDecimal leaseSum = entireLeaseArea.add(fractionalLeaseArea); + BigDecimal dailyRate = widTotalArea.compareTo(BigDecimal.ZERO) == 0 + ? BigDecimal.ZERO + : leaseSum.multiply(new BigDecimal("100")).divide(widTotalArea, 2, BigDecimal.ROUND_HALF_UP); + vo.setDailyRentalRate(dailyRate); exportList.add(vo); } - // ===== 5. 按业务日期降序排序(null 排最后)===== + // ===== 5. 按业务日期降序、仓库名升序排序(null 排最后)===== exportList.sort(Comparator .comparing(WarehouseLeaseExportVO::getBusinessDate, Comparator.nullsLast(Comparator.reverseOrder())) .thenComparing(WarehouseLeaseExportVO::getWarehouseName, Comparator.nullsLast(Comparator.naturalOrder())));