Jelajahi Sumber

新增
1、长者页面点餐模块
修改
1、修改推送金蝶应收单日期为账单月末

liangwenxuan 3 bulan lalu
induk
melakukan
d8fbe61ee7
18 mengubah file dengan 837 tambahan dan 5 penghapusan
  1. 5 5
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/kingdee/KingdeeApiImpl.java
  2. 9 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/BuildController.java
  3. 88 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/ElderlyOrderFoodController.java
  4. 68 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/BuildFloorTreeRespVO.java
  5. 36 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderOrderFoodExportExcelVO.java
  6. 38 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodCommitVO.java
  7. 16 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodGetReqVO.java
  8. 56 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodGetResVO.java
  9. 36 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodPageReqVO.java
  10. 34 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodRespVO.java
  11. 50 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/ElderlyOrderFoodDO.java
  12. 32 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/ElderlyOrderFoodMapper.java
  13. 2 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/BuildService.java
  14. 77 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/BuildServiceImpl.java
  15. 27 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyOrderFoodService.java
  16. 189 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyOrderFoodServiceImpl.java
  17. 70 0
      yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/ElderlyOrderFoodMapper.xml
  18. 4 0
      yudao-server/src/main/resources/application.yaml

+ 5 - 5
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/kingdee/KingdeeApiImpl.java

@@ -40,6 +40,7 @@ import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDate;
+import java.time.YearMonth;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
@@ -168,10 +169,9 @@ public class KingdeeApiImpl implements KingdeeApi {
                         .build();
                 FEntityDetailList.add(entityDetail);
             });
-            // date PayTime转换成yyyy-MM-dd字符串
-            String payTimeStr = DateUtils.formatDate(new Date(), DateUtils.FORMAT_YEAR_MONTH_DAY);
+            YearMonth yearMonth = YearMonth.parse(expenseOrderDO.getBillingMonth());
             ReceivableFsubHeadFinc headFinc = ReceivableFsubHeadFinc.builder()
-                    .FACCNTTIMEJUDGETIME(payTimeStr)
+                    .FACCNTTIMEJUDGETIME(yearMonth.atEndOfMonth().toString())
                     .FMAINBOOKSTDCURRID(KingdeeNumberDTO.builder().FNUMBER(FMAINBOOKSTDCURRID).build())
                     .FEXCHANGETYPE(KingdeeNumberDTO.builder().FNUMBER("HLTX01_SYS").build())
                     .FExchangeRate(new BigDecimal("1.0"))
@@ -183,9 +183,9 @@ public class KingdeeApiImpl implements KingdeeApi {
                     .FID(fid)
                     .FBillTypeID(KingdeeNumberDTO.builder().FNUMBER("YSD02_SYS").build())
                     .FBillNo(expenseOrderDO.getBillOrderNumber())
-                    .FDATE(payTimeStr)
+                    .FDATE(yearMonth.atEndOfMonth().toString())
                     .FISINIT(Boolean.FALSE.toString())
-                    .FENDDATE_H(expenseOrderDO.getBillingMonth())
+                    .FENDDATE_H(yearMonth.atEndOfMonth().toString())
                     .FSETTLEORGID(KingdeeNumberDTO.builder().FNUMBER(orgId).build())
                     .FCUSTOMERID(KingdeeNumberDTO.builder().FNUMBER(customerid).build())
                     .FCURRENCYID(KingdeeNumberDTO.builder().FNUMBER(FMAINBOOKSTDCURRID).build())

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

@@ -255,4 +255,13 @@ public class BuildController {
         }
         return success(buildService.getBuildFloorStatistics(tenantIds, month));
     }
+
+    @GetMapping("/getFloorTree")
+    @Operation(summary = "获取楼栋楼层房间树")
+    @TenantIgnore
+    @PermitAll
+    public CommonResult<List<BuildFloorTreeRespVO>> getFloorTree(
+            @RequestParam(value = "tenantId", required = false) Long tenantId) {
+        return success(buildService.getFloorTree(tenantId));
+    }
 }

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

@@ -0,0 +1,88 @@
+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.PageParam;
+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.tenant.core.aop.TenantIgnore;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.*;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.excel.DailyExpensesExportExcelVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.DailyExpensesDO;
+import cn.iocoder.yudao.module.system.service.biz.ElderlyOrderFoodService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+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 java.util.List;
+import java.util.Objects;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 长者报餐记录")
+@RestController
+@RequestMapping("/elderly/order-food")
+@Validated
+public class ElderlyOrderFoodController {
+
+    @Resource
+    private ElderlyOrderFoodService elderlyOrderFoodService;
+
+    @PostMapping("/commit")
+    @Operation(summary = "创建长者报餐记录")
+    @TenantIgnore
+    @PermitAll
+    public CommonResult<String> commit(@RequestBody List<ElderlyOrderFoodCommitVO> voList) {
+        return success(elderlyOrderFoodService.create(voList));
+    }
+
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除长者报餐记录")
+    @Parameter(name = "id", description = "编号", required = true)
+    public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
+        elderlyOrderFoodService.delete(id);
+        return success(true);
+    }
+
+    @PostMapping("/get")
+    @Operation(summary = "获得长者报餐记录")
+    @TenantIgnore
+    @PermitAll
+    public CommonResult<List<ElderlyOrderFoodGetResVO>> get(@RequestBody ElderlyOrderFoodGetReqVO reqVO) {
+        return success(elderlyOrderFoodService.get(reqVO));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得长者报餐记录分页")
+    @TenantIgnore
+    public CommonResult<PageResult<ElderlyOrderFoodRespVO>> getPage(@Valid ElderlyOrderFoodPageReqVO pageReqVO) {
+        return success(elderlyOrderFoodService.getPage(pageReqVO));
+    }
+
+    @GetMapping("/exportExcel")
+    @Operation(summary = "导出Excel")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportExcel(@Valid ElderlyOrderFoodPageReqVO reqVO,HttpServletResponse response) throws IOException {
+        List<ElderOrderFoodExportExcelVO> list = elderlyOrderFoodService.getList(reqVO);
+        // 导出 Excel
+        ExcelUtils.write(response, "长者点餐.xls", "数据", ElderOrderFoodExportExcelVO.class, list);
+    }
+}
+

+ 68 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/BuildFloorTreeRespVO.java

@@ -0,0 +1,68 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Schema(description = "管理后台 - 楼栋楼层房间树 Response VO")
+@Data
+public class BuildFloorTreeRespVO implements Serializable {
+
+    @Schema(description = "楼栋ID", example = "1")
+    private Long buildingId;
+
+    @Schema(description = "楼栋名称", example = "A栋")
+    private String buildingName;
+
+    @Schema(description = "楼层列表")
+    private List<FloorVO> floorList;
+
+    @Data
+    public static class FloorVO implements Serializable {
+
+        @Schema(description = "楼层ID", example = "11")
+        private Long floorId;
+
+        @Schema(description = "楼层名称", example = "6层")
+        private String floorName;
+
+        @Schema(description = "房间列表")
+        private List<RoomVO> roomList;
+    }
+
+    @Data
+    public static class RoomVO implements Serializable {
+
+        @Schema(description = "房间ID", example = "101")
+        private Long roomId;
+
+        @Schema(description = "房间名称", example = "601")
+        private String roomName;
+
+        @Schema(description = "是否完成", example = "false")
+        private Boolean isFinish;
+
+        @Schema(description = "床位列表")
+        private List<BedVO> bedList;
+    }
+
+    @Data
+    public static class BedVO implements Serializable {
+
+        @Schema(description = "床位id", example = "101")
+        private Long bedId;
+
+        @Schema(description = "床位名称", example = "601")
+        private String bedName;
+
+        @Schema(description = "长者id", example = "101")
+        private Long elderId;
+
+        @Schema(description = "长者名称", example = "601")
+        private String elderName;
+
+    }
+}
+

+ 36 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderOrderFoodExportExcelVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
+public class ElderOrderFoodExportExcelVO {
+    @ExcelProperty("楼栋名称")
+    private String buildName;
+
+    @ExcelProperty("楼层名称")
+    private String floorName;
+
+    @ExcelProperty("房间号")
+    private String roomName;
+
+    @ExcelProperty("长者姓名")
+    private String elderName;
+
+    @ExcelProperty("日期")
+    private LocalDate orderFoodDate;
+
+    @ExcelProperty("附加菜名")
+    private String extraDishes;
+}

+ 38 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodCommitVO.java

@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.*;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Data
+@ToString
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ElderlyOrderFoodCommitVO {
+    /**
+     * 长者id
+     */
+    private Long elderId;
+
+    /**
+     * 报餐日期
+     */
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    private LocalDate orderFoodDate;
+
+    /**
+     * 额外自选
+     */
+    private String extraDishes;
+
+    /**
+     * 机构id
+     */
+    private Long tenantId;
+}

+ 16 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodGetReqVO.java

@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - 长者报餐记录分页 Request VO")
+@Data
+@ToString(callSuper = true)
+public class ElderlyOrderFoodGetReqVO {
+    @Schema(description = "长者id", example = "1")
+    private Long elderId;
+
+    @Schema(description = "机构id", example = "1")
+    private Long tenantId;
+}

+ 56 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodGetResVO.java

@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyOrderFoodDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.CateringPlanItemDO;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
+
+@Data
+@ToString
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ElderlyOrderFoodGetResVO {
+
+    @Schema(description = "长者ID")
+    private Long elderId;
+
+    @Schema(description = "日期")
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    private LocalDate date;
+
+    @Schema(description = "星期几(如 MONDAY)")
+    private String dayOfWeek;
+
+    // ---------- 早餐 ----------
+    @Schema(description = "早餐固定餐")
+    private String breakfastFixed;
+
+    @Schema(description = "早餐可选菜品(供选择)")
+    private String breakfastOptional;
+
+    // ---------- 午餐 ----------
+    @Schema(description = "午餐固定餐")
+    private String lunchFixed;
+
+    @Schema(description = "午餐可选菜品")
+    private String lunchOptional;
+
+    // ---------- 晚餐 ----------
+    @Schema(description = "晚餐固定餐")
+    private String dinnerFixed;
+
+    @Schema(description = "晚餐可选菜品")
+    private String dinnerOptional;
+
+    // ---------- 长者已选额外自选(假设只针对午餐) ----------
+    @Schema(description = "长者已选额外自选(当前仅支持午餐)")
+    private String selectedExtra;
+}

+ 36 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodPageReqVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
+
+@Schema(description = "管理后台 - 长者报餐记录分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class ElderlyOrderFoodPageReqVO extends PageParam {
+
+    @Schema(description = "长者id", example = "1")
+    private Long elderId;
+
+    @Schema(description = "报餐日期")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    private LocalDate orderFoodDate;
+
+    @Schema(description = "机构id", example = "1")
+    private Long tenantId;
+
+    @Schema(description = "楼栋名称", example = "1")
+    private String buildName;
+
+    @Schema(description = "楼层名称", example = "1")
+    private String floorName;
+}
+

+ 34 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyOrderFoodRespVO.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
+
+@Schema(description = "管理后台 - 长者报餐记录 Response VO")
+@Data
+public class ElderlyOrderFoodRespVO {
+
+    @Schema(description = "id", example = "1")
+    private Long id;
+
+    @Schema(description = "长者id", example = "1")
+    private Long elderId;
+
+    @Schema(description = "长者姓名", example = "1")
+    private String elderName;
+
+    @Schema(description = "报餐日期")
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    private LocalDate orderFoodDate;
+
+    @Schema(description = "额外自选")
+    private String extraDishes;
+
+    @Schema(description = "机构id", example = "1")
+    private Long tenantId;
+}
+

+ 50 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/ElderlyOrderFoodDO.java

@@ -0,0 +1,50 @@
+package cn.iocoder.yudao.module.system.dal.dataobject.biz;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+import java.time.LocalDate;
+
+/**
+ * 长者周报餐记录 DO
+ */
+@TableName("elderly_order_food")
+@KeySequence("elderly_order_food_seq")
+@Data
+@ToString
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ElderlyOrderFoodDO {
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 长者id
+     */
+    private Long elderId;
+
+    /**
+     * 报餐日期
+     */
+    private LocalDate orderFoodDate;
+
+    /**
+     * 额外自选
+     */
+    private String extraDishes;
+
+    /**
+     * 机构id
+     */
+    private Long tenantId;
+}
+

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

@@ -0,0 +1,32 @@
+package cn.iocoder.yudao.module.system.dal.mysql.biz;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ElderOrderFoodExportExcelVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ElderlyOrderFoodPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ElderlyOrderFoodRespVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyOrderFoodDO;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface ElderlyOrderFoodMapper extends BaseMapperX<ElderlyOrderFoodDO> {
+
+    default PageResult<ElderlyOrderFoodDO> selectPage(ElderlyOrderFoodPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<ElderlyOrderFoodDO>()
+                .eqIfPresent(ElderlyOrderFoodDO::getElderId, reqVO.getElderId())
+                .eqIfPresent(ElderlyOrderFoodDO::getOrderFoodDate, reqVO.getOrderFoodDate())
+                .eqIfPresent(ElderlyOrderFoodDO::getTenantId, reqVO.getTenantId())
+                .orderByDesc(ElderlyOrderFoodDO::getId));
+    }
+
+
+    List<ElderlyOrderFoodRespVO> selectPageWithDetail(IPage<ElderlyOrderFoodRespVO> page, @Param("reqVO") ElderlyOrderFoodPageReqVO reqVO);
+    List<ElderOrderFoodExportExcelVO> getList(@Param("reqVO") ElderlyOrderFoodPageReqVO reqVO);
+}
+

+ 2 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/BuildService.java

@@ -76,4 +76,6 @@ public interface BuildService {
      * @return 楼栋楼层统计信息
      */
     BuildFloorStatisticsRespVO getBuildFloorStatistics(Long[] tenantIds, String month);
+
+    List<BuildFloorTreeRespVO> getFloorTree(Long tenantId);
 }

+ 77 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/BuildServiceImpl.java

@@ -33,6 +33,7 @@ import com.alibaba.fastjson.JSON;
 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
@@ -94,6 +95,9 @@ public class BuildServiceImpl implements BuildService {
     @Resource
     private DictDataMapper dictDataMapper;
 
+    @Autowired
+    private ElderlyOrderFoodMapper elderlyOrderFoodMapper;
+
     @Override
     public Long createBuild(BuildSaveReqVO createReqVO) {
         BuildDO buildDO = new BuildDO();
@@ -871,6 +875,56 @@ public class BuildServiceImpl implements BuildService {
         return collect;
     }
 
+    @Override
+    public List<BuildFloorTreeRespVO> getFloorTree(Long tenantId) {
+        List<BuildDO> buildList = buildMapper.selectList(new LambdaQueryWrapperX<BuildDO>()
+                .eq(BuildDO::getTenantId, tenantId)
+                .orderByAsc(BuildDO::getSort));
+        if (CollectionUtil.isEmpty(buildList)) {
+            return Collections.emptyList();
+        }
+        List<Long> buildIds = buildList.stream().map(BuildDO::getId).collect(Collectors.toList());
+        List<BuildFloorDO> floorList = buildFloorMapper.selectList(new LambdaQueryWrapperX<BuildFloorDO>()
+                .in(BuildFloorDO::getBuildId, buildIds)
+                .orderByAsc(BuildFloorDO::getSort));
+        Map<Long, List<BuildFloorDO>> floorMap = floorList.stream()
+                .collect(Collectors.groupingBy(BuildFloorDO::getBuildId, LinkedHashMap::new, Collectors.toList()));
+        List<Long> floorIds = floorList.stream().map(BuildFloorDO::getId).collect(Collectors.toList());
+        Map<Long, List<BuildRoomDO>> roomMap = Collections.emptyMap();
+        if (CollectionUtil.isNotEmpty(floorIds)) {
+            List<BuildRoomDO> roomList = buildRoomMapper.selectList(new LambdaQueryWrapperX<BuildRoomDO>()
+                    .in(BuildRoomDO::getFloorId, floorIds)
+                    .orderByAsc(BuildRoomDO::getId));
+            roomMap = roomList.stream().collect(Collectors.groupingBy(BuildRoomDO::getFloorId, LinkedHashMap::new, Collectors.toList()));
+        }
+        List<BuildFloorTreeRespVO> result = new ArrayList<>();
+        for (BuildDO build : buildList) {
+            BuildFloorTreeRespVO buildVO = new BuildFloorTreeRespVO();
+            buildVO.setBuildingId(build.getId());
+            buildVO.setBuildingName(build.getBuildName());
+            List<BuildFloorTreeRespVO.FloorVO> floorVOList = new ArrayList<>();
+            for (BuildFloorDO floor : floorMap.getOrDefault(build.getId(), Collections.emptyList())) {
+                BuildFloorTreeRespVO.FloorVO floorVO = new BuildFloorTreeRespVO.FloorVO();
+                floorVO.setFloorId(floor.getId());
+                floorVO.setFloorName(floor.getFloorName());
+                List<BuildFloorTreeRespVO.RoomVO> roomVOList = roomMap.getOrDefault(floor.getId(), Collections.emptyList())
+                        .stream()
+                        .map(room -> {
+                            BuildFloorTreeRespVO.RoomVO roomVO = new BuildFloorTreeRespVO.RoomVO();
+                            roomVO.setRoomId(room.getId());
+                            roomVO.setRoomName(room.getRoomName());
+                            handleIsFinishAndBedList(roomVO);
+                            return roomVO;
+                        }).collect(Collectors.toList());
+                floorVO.setRoomList(roomVOList);
+                floorVOList.add(floorVO);
+            }
+            buildVO.setFloorList(floorVOList);
+            result.add(buildVO);
+        }
+        return result;
+    }
+
     @Override
     public BuildFloorStatisticsRespVO getBuildFloorStatistics(Long[] tenantIds, String month) {
         BuildFloorStatisticsRespVO respVO = new BuildFloorStatisticsRespVO();
@@ -1364,4 +1418,27 @@ public class BuildServiceImpl implements BuildService {
                 .atZone(ZoneId.systemDefault())
                 .toInstant());
     }
+
+    private void handleIsFinishAndBedList(BuildFloorTreeRespVO.RoomVO roomVO){
+        List<ElderlyInfoDO> elderlyInfoList = elderlyInfoMapper.selectList(new LambdaQueryWrapperX<ElderlyInfoDO>()
+                .eq(ElderlyInfoDO::getRoomId, roomVO.getRoomId()));
+        List<BuildFloorTreeRespVO.BedVO> bedList = new ArrayList<>();
+        boolean isFinish = true;
+        for (ElderlyInfoDO elderlyInfoDO : elderlyInfoList) {
+            BuildFloorTreeRespVO.BedVO bedVO = new BuildFloorTreeRespVO.BedVO();
+            bedVO.setBedId(elderlyInfoDO.getBedId());
+            bedVO.setBedName(elderlyInfoDO.getBedName());
+            bedVO.setElderId(elderlyInfoDO.getId());
+            bedVO.setElderName(elderlyInfoDO.getElderName());
+            bedList.add(bedVO);
+            ElderlyOrderFoodDO orderFoodDO = elderlyOrderFoodMapper.selectOne(new LambdaQueryWrapperX<ElderlyOrderFoodDO>()
+                    .eq(ElderlyOrderFoodDO::getElderId, elderlyInfoDO.getId())
+                    .eq(ElderlyOrderFoodDO::getOrderFoodDate, LocalDate.now()));
+            if(orderFoodDO == null){
+                isFinish = false;
+            }
+        }
+        roomVO.setBedList(bedList);
+        roomVO.setIsFinish(isFinish);
+    }
 }

+ 27 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyOrderFoodService.java

@@ -0,0 +1,27 @@
+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.*;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyOrderFoodDO;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * 长者报餐记录 Service 接口
+ */
+public interface ElderlyOrderFoodService {
+
+    String create(List<ElderlyOrderFoodCommitVO> voList);
+
+    void update(@Valid ElderlyOrderFoodDO updateReqVO);
+
+    void delete(Long id);
+
+    List<ElderlyOrderFoodGetResVO> get(ElderlyOrderFoodGetReqVO reqVO);
+
+    PageResult<ElderlyOrderFoodRespVO> getPage(ElderlyOrderFoodPageReqVO pageReqVO);
+
+    List<ElderOrderFoodExportExcelVO> getList(ElderlyOrderFoodPageReqVO reqVO);
+}
+

+ 189 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyOrderFoodServiceImpl.java

@@ -0,0 +1,189 @@
+package cn.iocoder.yudao.module.system.service.biz;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.*;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyOrderFoodDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.CateringPlanDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.CateringPlanItemDO;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyOrderFoodMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.restaurant.CateringPlanItemMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.restaurant.CateringPlanMapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import kotlin.jvm.internal.Lambda;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+import java.lang.reflect.Field;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.temporal.TemporalAdjusters;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.COMMON_NOT_FOUND;
+
+@Service
+@Validated
+public class ElderlyOrderFoodServiceImpl implements ElderlyOrderFoodService {
+
+    @Resource
+    private ElderlyOrderFoodMapper elderlyOrderFoodMapper;
+
+    @Autowired
+    private CateringPlanMapper cateringPlanMapper;
+
+    @Autowired
+    private CateringPlanItemMapper cateringPlanItemMapper;
+
+    @Override
+    public String create(List<ElderlyOrderFoodCommitVO> voList) {
+        Map<Long, List<ElderlyOrderFoodCommitVO>> map = voList.stream()
+                .collect(Collectors.groupingBy(ElderlyOrderFoodCommitVO::getElderId));
+        for (Long elderId : map.keySet()) {
+            ElderlyOrderFoodCommitVO firstItem = map.get(elderId).get(0);
+            LocalDate orderFoodDate = firstItem.getOrderFoodDate();
+            LocalDate endDate = orderFoodDate.plusDays(6);
+            elderlyOrderFoodMapper.delete(new LambdaQueryWrapperX<ElderlyOrderFoodDO>()
+                    .eq(ElderlyOrderFoodDO::getElderId, elderId)
+                    .eq(ElderlyOrderFoodDO::getTenantId, firstItem.getTenantId())
+                    .between(ElderlyOrderFoodDO::getOrderFoodDate, orderFoodDate, endDate));
+        }
+        List<ElderlyOrderFoodDO> insertList = voList.stream()
+                .map(vo -> {
+                    ElderlyOrderFoodDO doObj = new ElderlyOrderFoodDO();
+                    BeanUtils.copyProperties(vo, doObj);
+                    return doObj;
+                })
+                .collect(Collectors.toList());
+        elderlyOrderFoodMapper.insertBatch(insertList);
+        return "success";
+    }
+
+    @Override
+    public void update(ElderlyOrderFoodDO updateReqVO) {
+        validateExists(updateReqVO.getId());
+        elderlyOrderFoodMapper.updateById(updateReqVO);
+    }
+
+    @Override
+    public void delete(Long id) {
+        validateExists(id);
+        elderlyOrderFoodMapper.deleteById(id);
+    }
+
+    @Override
+    public List<ElderlyOrderFoodGetResVO> get(ElderlyOrderFoodGetReqVO reqVO) {
+        // 获取当前日期
+        LocalDate now = LocalDate.now();
+        // 本周一(第一天)
+        LocalDate monday = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
+        // 本周日(最后一天)
+        LocalDate sunday = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
+        CateringPlanDO cateringPlanDO = cateringPlanMapper.selectOne(new LambdaQueryWrapperX<CateringPlanDO>()
+                .eq(CateringPlanDO::getRestaurantId, 27)
+                .eq(CateringPlanDO::getScheduledStartDate,monday)
+                .eq(CateringPlanDO::getScheduledEndDate,sunday));
+        List<CateringPlanItemDO> cateringPlanItemDOS = cateringPlanItemMapper.selectList(new LambdaQueryWrapperX<CateringPlanItemDO>()
+                .eq(CateringPlanItemDO::getCateringPlanId, cateringPlanDO.getId())
+                .in(CateringPlanItemDO::getMealTimes, "早餐", "中餐", "晚餐"));
+
+        // 将餐次映射到对象
+        Map<String, CateringPlanItemDO> itemMap = cateringPlanItemDOS.stream()
+                .collect(Collectors.toMap(CateringPlanItemDO::getMealTimes, Function.identity()));
+
+        List<ElderlyOrderFoodGetResVO> week = new ArrayList<>();
+        LocalDate current = monday;
+        while (!current.isAfter(sunday)) {
+            String dayOfWeek = current.getDayOfWeek().name().toLowerCase(); // monday, tuesday...
+            ElderlyOrderFoodGetResVO daily = new ElderlyOrderFoodGetResVO();
+            daily.setElderId(reqVO.getElderId());
+            daily.setDate(current);
+            daily.setDayOfWeek(current.getDayOfWeek().toString()); // 如 MONDAY
+
+            // 早餐
+            CateringPlanItemDO breakfast = itemMap.get("早餐");
+            if (breakfast != null) {
+                daily.setBreakfastFixed(getFieldValue(breakfast, dayOfWeek));
+                daily.setBreakfastOptional(getFieldValue(breakfast, dayOfWeek + "Extra"));
+            }
+
+            // 午餐
+            CateringPlanItemDO lunch = itemMap.get("中餐");
+            if (lunch != null) {
+                daily.setLunchFixed(getFieldValue(lunch, dayOfWeek));
+                daily.setLunchOptional(getFieldValue(lunch, dayOfWeek + "Extra"));
+            }
+
+            // 晚餐
+            CateringPlanItemDO dinner = itemMap.get("晚餐");
+            if (dinner != null) {
+                daily.setDinnerFixed(getFieldValue(dinner, dayOfWeek));
+                daily.setDinnerOptional(getFieldValue(dinner, dayOfWeek + "Extra"));
+            }
+
+            week.add(daily);
+            current = current.plusDays(1);
+        }
+
+        // 5. 查询长者本周报餐记录
+        List<ElderlyOrderFoodDO> orders = elderlyOrderFoodMapper.selectList(
+                new LambdaQueryWrapper<ElderlyOrderFoodDO>()
+                        .eq(ElderlyOrderFoodDO::getElderId, reqVO.getElderId())
+                        .between(ElderlyOrderFoodDO::getOrderFoodDate, monday, sunday)
+        );
+        Map<LocalDate, String> orderMap = orders.stream()
+                .collect(Collectors.toMap(ElderlyOrderFoodDO::getOrderFoodDate, ElderlyOrderFoodDO::getExtraDishes));
+
+        // 将报餐信息合并到每日计划
+        for (ElderlyOrderFoodGetResVO daily : week) {
+            String extra = orderMap.get(daily.getDate());
+            if (extra != null) {
+                daily.setSelectedExtra(extra);
+            }
+        }
+        return week;
+    }
+
+    @Override
+    public PageResult<ElderlyOrderFoodRespVO> getPage(ElderlyOrderFoodPageReqVO pageReqVO) {
+        Page<ElderlyOrderFoodRespVO> page =  new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
+        List<ElderlyOrderFoodRespVO> data = elderlyOrderFoodMapper.selectPageWithDetail(page, pageReqVO);
+        return new PageResult<>(data, page.getTotal());
+    }
+
+    @Override
+    public List<ElderOrderFoodExportExcelVO> getList(ElderlyOrderFoodPageReqVO reqVO) {
+        return elderlyOrderFoodMapper.getList(reqVO);
+    }
+
+    private void validateExists(Long id) {
+        if (id == null || elderlyOrderFoodMapper.selectById(id) == null) {
+            throw exception(COMMON_NOT_FOUND);
+        }
+    }
+
+    // 反射获取字段值(生产环境建议用缓存或字段名映射)
+    private String getFieldValue(CateringPlanItemDO item, String fieldName) {
+        try {
+            Field field = CateringPlanItemDO.class.getDeclaredField(fieldName);
+            field.setAccessible(true);
+            return (String) field.get(item);
+        } catch (Exception e) {
+            // 字段可能不存在(如周六的 Extra 可能没配),返回空
+            return null;
+        }
+    }
+}
+

+ 70 - 0
yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/ElderlyOrderFoodMapper.xml

@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyOrderFoodMapper">
+
+    <select id="selectPageWithDetail"
+            resultType="cn.iocoder.yudao.module.system.controller.admin.biz.vo.ElderlyOrderFoodRespVO">
+        SELECT eof.id,
+               eof.elder_id AS elderId,
+               ei.elder_name AS elderName,
+               b.build_name AS buildName,
+               f.floor_name AS floorName,
+               r.room_name AS roomName,
+               eof.order_food_date AS orderFoodDate,
+               eof.extra_dishes AS extraDishes,
+               eof.tenant_id AS tenantId
+        FROM elderly_order_food eof
+                 LEFT JOIN elderly_info ei ON ei.id = eof.elder_id
+                 LEFT JOIN org_build b ON b.id = ei.build_id
+                 LEFT JOIN org_build_floor f ON f.id = ei.floor_id
+                 LEFT JOIN org_build_room r ON r.id = ei.room_id
+        WHERE 1 = 1
+        <if test="reqVO.tenantId != null">
+            AND eof.tenant_id = #{reqVO.tenantId}
+        </if>
+        <if test="reqVO.buildName != null and reqVO.buildName != ''">
+            AND b.build_name like concat('%',#{reqVO.buildName},'%')
+        </if>
+        <if test="reqVO.floorName != null and  reqVO.floorName != ''">
+            AND f.floor_name like concat('%',#{reqVO.floorName},'%')
+        </if>
+        <if test="reqVO.orderFoodDate != null">
+            AND eof.order_food_date = #{reqVO.orderFoodDate}
+        </if>
+        ORDER BY eof.order_food_date DESC, eof.id DESC
+    </select>
+
+    <select id="getList"
+            resultType="cn.iocoder.yudao.module.system.controller.admin.biz.vo.ElderOrderFoodExportExcelVO">
+        SELECT eof.id,
+        eof.elder_id AS elderId,
+        ei.elder_name AS elderName,
+        b.build_name AS buildName,
+        f.floor_name AS floorName,
+        r.room_name AS roomName,
+        eof.order_food_date AS orderFoodDate,
+        eof.extra_dishes AS extraDishes,
+        eof.tenant_id AS tenantId
+        FROM elderly_order_food eof
+        LEFT JOIN elderly_info ei ON ei.id = eof.elder_id
+        LEFT JOIN org_build b ON b.id = ei.build_id
+        LEFT JOIN org_build_floor f ON f.id = ei.floor_id
+        LEFT JOIN org_build_room r ON r.id = ei.room_id
+        WHERE 1 = 1
+        <if test="reqVO.tenantId != null">
+            AND eof.tenant_id = #{reqVO.tenantId}
+        </if>
+        <if test="reqVO.buildName != null and reqVO.buildName != ''">
+            AND b.build_name like concat('%',#{reqVO.buildName},'%')
+        </if>
+        <if test="reqVO.floorName != null and  reqVO.floorName != ''">
+            AND f.floor_name like concat('%',#{reqVO.floorName},'%')
+        </if>
+        <if test="reqVO.orderFoodDate != null">
+            AND eof.order_food_date = #{reqVO.orderFoodDate}
+        </if>
+        ORDER BY b.build_name DESC, f.floor_name DESC, r.room_name DESC, eof.order_food_date DESC
+    </select>
+
+</mapper>
+

+ 4 - 0
yudao-server/src/main/resources/application.yaml

@@ -227,6 +227,10 @@ yudao:
       - /admin-api/internal/proxy
       - /admin-api/pay/wx/unifiedOrder
       - /admin-api/pay/wx/callback
+      - /admin-api/build/getFloorTree
+      - /admin-api/elderly/order-food/commit
+      - /admin-api/elderly/order-food/get
+      - /admin-api/elderly/order-food/page
     ignore-tables:
       - system_tenant
       - system_groups