Forráskód Böngészése

新增
1、新增巡房项目日志导出
BUGFIX
1、解决日常费用无法补录到目标账单问题

liangwenxuan 2 hete
szülő
commit
5fa992fd5c

+ 13 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/ElderlyItemsRoundController.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.system.controller.admin.biz;
 
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
@@ -21,8 +22,11 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.annotation.security.PermitAll;
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
+import java.io.IOException;
 
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 长者巡房项目")
@@ -90,4 +94,13 @@ public class ElderlyItemsRoundController {
         }
         return success(elderlyItemsRoundService.batchCreate(reqVO));
     }
+
+    @GetMapping("/exportExcel")
+    @Operation(summary = "导出长者巡房项目 Excel")
+    @ApiAccessLog(operateType = EXPORT)
+    @TenantIgnore
+    public void exportExcel(@RequestParam("yearMonth") String yearMonth,
+                            HttpServletResponse response) throws IOException {
+        elderlyItemsRoundService.exportExcel(yearMonth, response);
+    }
 }

+ 2 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/ElderlyInfoMapper.java

@@ -54,4 +54,6 @@ public interface ElderlyInfoMapper extends BaseMapperX<ElderlyInfoDO> {
 
     List<ElderlyVitalSignsStatisticsTodayRespVO> selectVitalSignsTodayList(@Param("page") Page<BedChangeRecordRespVO> page,
                                                                            @Param("pageReqVO") ElderlyVitalSignsMainPageReqVO pageReqVO);
+
+    List<ElderlyInfoDO> selectExportListWithBedInfo(@Param("tenantId") Long tenantId);
 }

+ 6 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/ElderlyItemsRoundMapper.java

@@ -10,8 +10,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
-import java.time.LocalTime;
+import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Map;
 
 @Mapper
 public interface ElderlyItemsRoundMapper extends BaseMapperX<ElderlyItemsRoundDO> {
@@ -21,6 +22,10 @@ public interface ElderlyItemsRoundMapper extends BaseMapperX<ElderlyItemsRoundDO
 
     ElderlyItemsRoundDO selectByIdWithElderInfo(@Param("id") Long id);
 
+    List<Map<String, Object>> selectMonthDayMinStatus(@Param("tenantId") Long tenantId,
+                                                      @Param("startTime") LocalDateTime startTime,
+                                                      @Param("endTime") LocalDateTime endTime);
+
     default PageResult<ElderlyItemsRoundPageRespVO> selectPageWithElderInfo(ElderlyItemsRoundPageReqVO reqVO) {
         Page<ElderlyItemsRoundPageRespVO> page = new Page<>(reqVO.getPageNo(), reqVO.getPageSize());
         List<ElderlyItemsRoundPageRespVO> list = selectPageWithElderInfo(page, reqVO);

+ 5 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyItemsRoundService.java

@@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.service.biz;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.elderlyitemsround.*;
 
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
 public interface ElderlyItemsRoundService {
 
     Long create(ElderlyItemsRoundSaveReqVO createReqVO);
@@ -16,4 +19,6 @@ public interface ElderlyItemsRoundService {
     PageResult<ElderlyItemsRoundPageRespVO> getPage(ElderlyItemsRoundPageReqVO pageReqVO);
 
     Boolean batchCreate(ElderlyItemsRoundBatchSaveReqVO reqVO);
+
+    void exportExcel(String yearMonth, HttpServletResponse response) throws IOException;
 }

+ 280 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyItemsRoundServiceImpl.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.biz;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.elderlyitemsround.*;
@@ -11,11 +12,33 @@ import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyItemsRoundDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyItemsRoundMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.converters.longconverter.LongStringConverter;
+import com.alibaba.excel.write.handler.SheetWriteHandler;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.util.CellRangeAddress;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.YearMonth;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -114,6 +137,125 @@ public class ElderlyItemsRoundServiceImpl implements ElderlyItemsRoundService {
         return elderlyItemsRoundMapper.insertBatch(insertList);
     }
 
+    @Override
+    public void exportExcel(String yearMonth, HttpServletResponse response) throws IOException {
+        YearMonth ym = parseYearMonth(yearMonth);
+        Long tenantId = TenantContextHolder.getTenantId();
+
+        List<ElderlyInfoDO> elderlyList = elderlyInfoMapper.selectExportListWithBedInfo(tenantId);
+
+        int daysInMonth = ym.lengthOfMonth();
+        int colCount = 2 + daysInMonth;
+
+        Map<Long, Map<Integer, String>> elderDayStatusMap = new HashMap<>();
+        LocalDateTime start = ym.atDay(1).atStartOfDay();
+        LocalDateTime endExclusive = ym.plusMonths(1).atDay(1).atStartOfDay();
+        List<Map<String, Object>> dayStatusList = elderlyItemsRoundMapper.selectMonthDayMinStatus(tenantId, start, endExclusive);
+        for (Map<String, Object> row : dayStatusList) {
+            if (row == null) {
+                continue;
+            }
+            Object elderIdValue = row.get("elderId");
+            Object dayValue = row.get("day");
+            Object minStatusValue = row.get("minStatus");
+            if (!(elderIdValue instanceof Number) || !(dayValue instanceof Number) || !(minStatusValue instanceof Boolean)) {
+                continue;
+            }
+            Long elderId = ((Number) elderIdValue).longValue();
+            Integer day = ((Number) dayValue).intValue();
+            Boolean minStatus = ((Boolean) minStatusValue);
+
+            Map<Integer, String> dayMap = elderDayStatusMap.computeIfAbsent(elderId, k -> new HashMap<>());
+            dayMap.put(day, !minStatus ? "△" : "√");
+        }
+
+        Map<String, List<ElderlyInfoDO>> buildGroups = new LinkedHashMap<>();
+        for (ElderlyInfoDO elderly : elderlyList) {
+            String buildName = StrUtil.blankToDefault(elderly.getBuildName(), "未分配楼栋");
+            buildGroups.computeIfAbsent(buildName, k -> new ArrayList<>()).add(elderly);
+        }
+
+        String filename = "长者巡房项目-" + ym + ".xlsx";
+        ExcelUtils.setResponseProperties(response, filename);
+
+        Map<String, List<List<String>>> sheetRows = new LinkedHashMap<>();
+        Map<String, List<Integer>> sheetMergeRows = new LinkedHashMap<>();
+
+        if (buildGroups.isEmpty()) {
+            String sheetName = uniqueSheetName("无数据", sheetRows);
+            List<List<String>> rows = new ArrayList<>();
+            rows.add(padRow("长者巡房项目(" + ym + ")", colCount));
+            rows.add(padRow("无符合条件的长者数据", colCount));
+            sheetRows.put(sheetName, rows);
+            sheetMergeRows.put(sheetName, new ArrayList<>(Collections.singletonList(0)));
+        } else {
+            List<Map.Entry<String, List<ElderlyInfoDO>>> buildEntries = new ArrayList<>(buildGroups.entrySet());
+            buildEntries.sort(Map.Entry.comparingByKey(Comparator.nullsLast(String::compareTo)));
+            for (Map.Entry<String, List<ElderlyInfoDO>> buildEntry : buildEntries) {
+                String rawSheetName = sanitizeSheetName(buildEntry.getKey());
+                String sheetName = uniqueSheetName(rawSheetName, sheetRows);
+
+                List<ElderlyInfoDO> buildElders = buildEntry.getValue();
+                buildElders.sort(Comparator
+                        .comparing((ElderlyInfoDO e) -> StrUtil.blankToDefault(e.getFloorName(), ""))
+                        .thenComparing(e -> StrUtil.blankToDefault(e.getRoomName(), ""))
+                        .thenComparing(e -> StrUtil.blankToDefault(e.getBedName(), ""))
+                        .thenComparing(e -> StrUtil.blankToDefault(e.getElderName(), "")));
+
+                List<List<String>> rows = new ArrayList<>();
+                List<Integer> mergeRows = new ArrayList<>();
+
+                rows.add(padRow(buildEntry.getKey() + " 长者巡房项目(" + ym + ")", colCount));
+                mergeRows.add(0);
+                rows.add(blankRow(colCount));
+
+                int rowIndex = 2;
+                Map<String, List<ElderlyInfoDO>> floorGroups = new LinkedHashMap<>();
+                for (ElderlyInfoDO elderly : buildElders) {
+                    String floorName = StrUtil.blankToDefault(elderly.getFloorName(), "未分配楼层");
+                    floorGroups.computeIfAbsent(floorName, k -> new ArrayList<>()).add(elderly);
+                }
+
+                List<Map.Entry<String, List<ElderlyInfoDO>>> floorEntries = new ArrayList<>(floorGroups.entrySet());
+                floorEntries.sort(Map.Entry.comparingByKey(Comparator.nullsLast(String::compareTo)));
+                for (Map.Entry<String, List<ElderlyInfoDO>> floorEntry : floorEntries) {
+                    rows.add(padRow(floorEntry.getKey(), colCount));
+                    mergeRows.add(rowIndex);
+                    rowIndex++;
+
+                    rows.add(headerRow(daysInMonth));
+                    rowIndex++;
+
+                    for (ElderlyInfoDO elderly : floorEntry.getValue()) {
+                        rows.add(dataRow(elderly, elderDayStatusMap.get(elderly.getId()), daysInMonth));
+                        rowIndex++;
+                    }
+
+                    rows.add(blankRow(colCount));
+                    rowIndex++;
+                }
+
+                sheetRows.put(sheetName, rows);
+                sheetMergeRows.put(sheetName, mergeRows);
+            }
+        }
+
+        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
+                .autoCloseStream(false)
+                .registerConverter(new LongStringConverter())
+                .registerWriteHandler(new SheetLayoutWriteHandler(sheetMergeRows, colCount - 1, 10, 32, 4))
+                .build();
+        try {
+            int sheetNo = 0;
+            for (Map.Entry<String, List<List<String>>> entry : sheetRows.entrySet()) {
+                WriteSheet sheet = EasyExcel.writerSheet(sheetNo++, entry.getKey()).build();
+                excelWriter.write(entry.getValue(), sheet);
+            }
+        } finally {
+            excelWriter.finish();
+        }
+    }
+
     private void fillDefault(ElderlyItemsRoundDO record) {
         if (record.getTenantId() == null) {
             record.setTenantId(TenantContextHolder.getTenantId());
@@ -141,4 +283,142 @@ public class ElderlyItemsRoundServiceImpl implements ElderlyItemsRoundService {
             throw exception(COMMON_NOT_FOUND);
         }
     }
+
+    private static YearMonth parseYearMonth(String value) {
+        if (StrUtil.isBlank(value)) {
+            throw invalidParamException("yearMonth不能为空");
+        }
+        String v = value.trim();
+        Pattern p1 = Pattern.compile("^(\\d{4})-(0[1-9]|1[0-2])$");
+        Matcher m1 = p1.matcher(v);
+        if (m1.matches()) {
+            return YearMonth.of(Integer.parseInt(m1.group(1)), Integer.parseInt(m1.group(2)));
+        }
+        Pattern p2 = Pattern.compile("^(\\d{4})(0[1-9]|1[0-2])$");
+        Matcher m2 = p2.matcher(v);
+        if (m2.matches()) {
+            return YearMonth.of(Integer.parseInt(m2.group(1)), Integer.parseInt(m2.group(2)));
+        }
+        throw invalidParamException("yearMonth格式错误,示例:2026-05 或 202605");
+    }
+
+    private static String sanitizeSheetName(String name) {
+        String v = StrUtil.blankToDefault(name, "Sheet");
+        v = v.replaceAll("[\\\\/?*\\[\\]:]", " ");
+        v = v.trim();
+        if (v.length() > 31) {
+            v = v.substring(0, 31);
+        }
+        return StrUtil.blankToDefault(v, "Sheet");
+    }
+
+    private static String uniqueSheetName(String baseName, Map<String, ?> existing) {
+        String base = sanitizeSheetName(baseName);
+        if (!existing.containsKey(base)) {
+            return base;
+        }
+        for (int i = 2; i < 1000; i++) {
+            String suffix = "(" + i + ")";
+            int maxLen = 31 - suffix.length();
+            String candidateBase = base.length() > maxLen ? base.substring(0, maxLen) : base;
+            String candidate = candidateBase + suffix;
+            if (!existing.containsKey(candidate)) {
+                return candidate;
+            }
+        }
+        return String.valueOf(System.currentTimeMillis());
+    }
+
+    private static List<String> padRow(String firstCell, int colCount) {
+        List<String> row = new ArrayList<>(colCount);
+        row.add(firstCell);
+        for (int i = 1; i < colCount; i++) {
+            row.add("");
+        }
+        return row;
+    }
+
+    private static List<String> blankRow(int colCount) {
+        List<String> row = new ArrayList<>(colCount);
+        for (int i = 0; i < colCount; i++) {
+            row.add("");
+        }
+        return row;
+    }
+
+    private static List<String> headerRow(int daysInMonth) {
+        int colCount = 2 + daysInMonth;
+        List<String> row = new ArrayList<>(colCount);
+        row.add("房号");
+        row.add("日期\\姓名");
+        for (int d = 1; d <= daysInMonth; d++) {
+            row.add(String.valueOf(d));
+        }
+        return row;
+    }
+
+    private static List<String> dataRow(ElderlyInfoDO elderly, Map<Integer, String> dayStatusMap, int daysInMonth) {
+        int colCount = 2 + daysInMonth;
+        List<String> row = new ArrayList<>(colCount);
+        row.add(StrUtil.blankToDefault(elderly.getRoomName(), ""));
+        String bed = StrUtil.blankToDefault(elderly.getBedName(), "");
+        String elderName = StrUtil.blankToDefault(elderly.getElderName(), "");
+        if (StrUtil.isBlank(bed)) {
+            row.add(elderName);
+        } else if (StrUtil.isBlank(elderName)) {
+            row.add(bed);
+        } else {
+            row.add(bed + "/" + elderName);
+        }
+        for (int d = 1; d <= daysInMonth; d++) {
+            String v = dayStatusMap != null ? dayStatusMap.get(d) : null;
+            row.add(StrUtil.blankToDefault(v, ""));
+        }
+        return row;
+    }
+
+    private static class SheetLayoutWriteHandler implements SheetWriteHandler {
+        private final Map<String, List<Integer>> sheetMergeRows;
+        private final int lastColIndex;
+        private final int roomColWidthChars;
+        private final int nameColWidthChars;
+        private final int dayColWidthChars;
+
+        private SheetLayoutWriteHandler(Map<String, List<Integer>> sheetMergeRows, int lastColIndex,
+                                        int roomColWidthChars, int nameColWidthChars, int dayColWidthChars) {
+            this.sheetMergeRows = sheetMergeRows;
+            this.lastColIndex = lastColIndex;
+            this.roomColWidthChars = roomColWidthChars;
+            this.nameColWidthChars = nameColWidthChars;
+            this.dayColWidthChars = dayColWidthChars;
+        }
+
+        @Override
+        public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
+        }
+
+        @Override
+        public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
+            Sheet sheet = writeSheetHolder.getSheet();
+            for (int col = 0; col <= lastColIndex; col++) {
+                if (col == 0) {
+                    sheet.setColumnWidth(col, roomColWidthChars * 256);
+                } else if (col == 1) {
+                    sheet.setColumnWidth(col, nameColWidthChars * 256);
+                } else {
+                    sheet.setColumnWidth(col, dayColWidthChars * 256);
+                }
+            }
+            List<Integer> rows = sheetMergeRows.get(writeSheetHolder.getSheetName());
+            if (rows == null) {
+                return;
+            }
+            for (Integer row : rows) {
+                if (row == null) {
+                    continue;
+                }
+                sheet.addMergedRegion(new CellRangeAddress(row, row, 0, lastColIndex));
+            }
+        }
+    }
 }

+ 2 - 31
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ExpenseOrderServiceImpl.java

@@ -838,7 +838,7 @@ public class ExpenseOrderServiceImpl implements ExpenseOrderService {
             YearMonth billingYm = YearMonth.parse(billingMonth, DateTimeFormatter.ofPattern("yyyy-MM"));
             LocalDate monthStart = billingYm.atDay(1);
             LocalDate monthEnd = billingYm.atEndOfMonth();
-            resultList.addAll(collectDailyExpenseItemsHasBill(elderId, billingMonth));
+            resultList.addAll(collectDailyExpenseItemsNoBill(elderId, billingMonth));
             resultList.addAll(collectSubsidyItems(elderId, billingMonth, monthStart, monthEnd, false));
             resultList.addAll(collectConsumerVoucherItems(elderId, billingMonth, monthStart, monthEnd, false));
             resultList.addAll(calculateDiscountDeduction(elderId, billingMonth));
@@ -880,35 +880,6 @@ public class ExpenseOrderServiceImpl implements ExpenseOrderService {
         }).collect(Collectors.toList());
     }
 
-    private List<ExpenseItemRespVO> collectDailyExpenseItemsHasBill(Long elderId, String billingMonth) {
-        YearMonth attributionBillTime = YearMonth.parse(billingMonth, DateTimeFormatter.ofPattern("yyyy-MM"));
-        List<DailyExpensesDO> dailyExpensesList = dailyExpensesMapper.selectList(new LambdaQueryWrapperX<DailyExpensesDO>()
-                .eq(DailyExpensesDO::getElderId, elderId)
-                .like(DailyExpensesDO::getAttributionBillTime, attributionBillTime)
-                .eq(DailyExpensesDO::getStatus, BooleanEnum.FALSE.getValue())
-                .eq(DailyExpensesDO::getIsGenerateBill, BooleanEnum.FALSE.getValue()));
-
-        return dailyExpensesList.stream().map(item -> {
-            ExpenseItemRespVO respVO = new ExpenseItemRespVO();
-            respVO.setExpenseType(item.getType());
-            respVO.setExpenseSource(BusinessConstants.DAILY_EXPENSES);
-            respVO.setSourceExpenseItemId(item.getId());
-            respVO.setPrice(item.getPrice());
-            respVO.setTotalAmount(item.getAmount());
-            respVO.setItemName(item.getItemName());
-            respVO.setItemCategory(item.getItemCategory());
-            respVO.setCount(item.getCount() == null ? 1 : item.getCount());
-            if (item.getStartDate() != null) {
-                respVO.setStartTime(item.getStartDate().toString());
-            }
-            if (item.getEndDate() != null) {
-                respVO.setEndTime(item.getEndDate().toString());
-            }
-            respVO.setDescription(item.getRemarks());
-            return respVO;
-        }).collect(Collectors.toList());
-    }
-
     private List<ExpenseItemRespVO> collectSubsidyItems(Long elderId, String billingMonth,
                                                          LocalDate startDate, LocalDate endDate,
                                                          boolean markUsed) {
@@ -2483,7 +2454,7 @@ public class ExpenseOrderServiceImpl implements ExpenseOrderService {
         }
 
         YearMonth attributionBillTime = YearMonth.parse(billingMonth, DateTimeFormatter.ofPattern("yyyy-MM"));
-        List<ExpenseItemRespVO> dataList = new ArrayList<>(collectDailyExpenseItemsHasBill(elderId, billingMonth));
+        List<ExpenseItemRespVO> dataList = new ArrayList<>(collectDailyExpenseItemsNoBill(elderId, billingMonth));
         dataList.addAll(collectSubsidyItems(elderId, billingMonth, attributionBillTime.atDay(1), attributionBillTime.atEndOfMonth(), true));
         dataList.addAll(collectConsumerVoucherItems(elderId, billingMonth, attributionBillTime.atDay(1), attributionBillTime.atEndOfMonth(), true));
         dataList.addAll(calculateDiscountDeduction(elderId, billingMonth));

+ 22 - 1
yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/ElderlyInfoMapper.xml

@@ -399,5 +399,26 @@
 
     </select>
 
+    <select id="selectExportListWithBedInfo" resultType="cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO">
+        SELECT
+            ei.id,
+            ei.elder_name AS elderName,
+            ob.build_name AS buildName,
+            obf.floor_name AS floorName,
+            obr.room_name AS roomName,
+            CONCAT_WS('-', ob.build_name, obf.floor_name, obr.room_name, obb.bed_name) AS bedName,
+            ei.bed_id AS bedId,
+            ei.tenant_id AS tenantId
+        FROM elderly_info ei
+        LEFT JOIN org_build_bed obb ON obb.id = ei.bed_id AND obb.tenant_id = ei.tenant_id
+        LEFT JOIN org_build_room obr ON obr.id = obb.room_id AND obr.tenant_id = obb.tenant_id
+        LEFT JOIN org_build_floor obf ON obf.id = obr.floor_id AND obf.tenant_id = obr.tenant_id
+        LEFT JOIN org_build ob ON ob.id = obf.build_id AND ob.tenant_id = obf.tenant_id
+        WHERE ei.tenant_id = #{tenantId}
+          AND ei.deleted = 0
+          AND ei.in_status = 1
+          AND ei.bed_id IS NOT NULL
+        ORDER BY ob.build_name, obf.floor_name, obr.room_name, obb.bed_name, ei.elder_name
+    </select>
 
-</mapper>
+</mapper>

+ 16 - 1
yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/ElderlyItemsRoundMapper.xml

@@ -43,5 +43,20 @@
         WHERE eir.id = #{id}
     </select>
 
-</mapper>
+    <select id="selectMonthDayMinStatus" resultType="java.util.HashMap">
+        SELECT
+            eir.elder_id AS elderId,
+            DAY(eir.round_time) AS day,
+            MIN(eir.status) AS minStatus
+        FROM elderly_items_round eir
+        INNER JOIN elderly_info ei ON ei.id = eir.elder_id AND ei.tenant_id = eir.tenant_id
+        WHERE eir.tenant_id = #{tenantId}
+          AND eir.round_time &gt;= #{startTime}
+          AND eir.round_time &lt; #{endTime}
+          AND ei.deleted = 0
+          AND ei.in_status = 1
+          AND ei.bed_id IS NOT NULL
+        GROUP BY eir.elder_id, DAY(eir.round_time)
+    </select>
 
+</mapper>