Преглед на файлове

新增
1、新增膳食调查模块
2、新增根据合同id查询费用信息、长者等相关信息接口

liangwenxuan преди 3 седмици
родител
ревизия
b9758e155d
променени са 16 файла, в които са добавени 842 реда и са изтрити 7 реда
  1. 30 0
      sql/mysql/food_satisfaction_survey.sql
  2. 5 4
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmElderlyChangeApiImpl.java
  3. 7 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/ElderlyInfoController.java
  4. 13 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/CheckInRecordDetailRespVO.java
  5. 123 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/evaluation/FoodSatisfactionSurveyController.java
  6. 29 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/evaluation/vo/FoodSatisfactionSurveyPageReqVO.java
  7. 95 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/evaluation/vo/FoodSatisfactionSurveyRespVO.java
  8. 88 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/evaluation/vo/FoodSatisfactionSurveySaveReqVO.java
  9. 87 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/evaluation/vo/excel/FoodSatisfactionSurveyExportExcelVO.java
  10. 111 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/evaluation/FoodSatisfactionSurveyDO.java
  11. 24 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/evaluation/FoodSatisfactionSurveyMapper.java
  12. 2 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyInfoService.java
  13. 127 3
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyInfoServiceImpl.java
  14. 22 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/evaluation/FoodSatisfactionSurveyService.java
  15. 78 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/evaluation/FoodSatisfactionSurveyServiceImpl.java
  16. 1 0
      yudao-server/src/main/resources/application.yaml

+ 30 - 0
sql/mysql/food_satisfaction_survey.sql

@@ -0,0 +1,30 @@
+DROP TABLE IF EXISTS `food_satisfaction_survey`;
+CREATE TABLE `food_satisfaction_survey` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `role` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '角色',
+  `record_date` date DEFAULT NULL COMMENT '记录日期',
+  `fresh` decimal(5, 2) DEFAULT NULL COMMENT '菜品新鲜度',
+  `taste` decimal(5, 2) DEFAULT NULL COMMENT '菜品口味(咸淡、口感等)',
+  `variety` decimal(5, 2) DEFAULT NULL COMMENT '菜品种类丰富度',
+  `staple` decimal(5, 2) DEFAULT NULL COMMENT '主食多样性(米饭、面食等)',
+  `soup` decimal(5, 2) DEFAULT NULL COMMENT '汤品 / 饮品口感与温度',
+  `nutrtion` decimal(5, 2) DEFAULT NULL COMMENT '菜品营养搭配合理性',
+  `tableware` decimal(5, 2) DEFAULT NULL COMMENT '餐具清洁程度',
+  `environment` decimal(5, 2) DEFAULT NULL COMMENT '用餐环境卫生(桌椅、地面等)',
+  `attitude` decimal(5, 2) DEFAULT NULL COMMENT '工作人员服务态度',
+  `timely` decimal(5, 2) DEFAULT NULL COMMENT '菜品供应及时性(未出现长时间断供)',
+  `portion` decimal(5, 2) DEFAULT NULL COMMENT '菜品分量充足度',
+  `soft_food` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '是否满足软食需求',
+  `vegetarian` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '是否满足素食需求',
+  `allergy_label` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '对有过敏食材的人群,是否能提供明确的食材标注',
+  `improve` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '最需要改进的方面',
+  `new_dishes` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '希望新增哪些菜品或服务',
+  `other` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '其他想反馈的内容',
+  `quality_total` decimal(5, 2) DEFAULT NULL COMMENT '膳食质量评价总分',
+  `service_total` decimal(5, 2) DEFAULT NULL COMMENT '膳食服务评价总分',
+  `submitter` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '提交人',
+  `tenant_id` bigint(20) DEFAULT NULL COMMENT '机构id',
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='膳食满意度调查' ROW_FORMAT=Dynamic;

+ 5 - 4
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmElderlyChangeApiImpl.java

@@ -526,9 +526,9 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
         // 4. 更新月度账单配置
         List<ExpenseItemDO> expenseItemDOS = expenseItemMapper.selectList(new LambdaQueryWrapperX<ExpenseItemDO>()
                 .eq(ExpenseItemDO::getExpenseId, chargeCategory.getExpenseId()));
-        ExpenseDO expenseDO = new ExpenseDO();
-        expenseMapper.insert(expenseDO.setElderId(elderlyId)
-                .setCreatedTime(new Date())
+        ExpenseDO expenseDO = expenseMapper.selectById(chargeCategory.getExpenseId());
+        expenseDO.setId(null);
+        expenseMapper.insert(expenseDO.setCreatedTime(new Date())
                 .setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname())
                 .setTenantId(startTenantId));
         BigDecimal totalAmout = BigDecimal.ZERO;
@@ -659,7 +659,8 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
         }
         List<ExpenseItemDO> expenseItemDOS = expenseItemMapper.selectList(new LambdaQueryWrapperX<ExpenseItemDO>()
                 .eq(ExpenseItemDO::getExpenseId, categoryList.get(0).getExpenseId()));
-        ExpenseDO expenseDO = new ExpenseDO();
+        ExpenseDO expenseDO = expenseMapper.selectById(categoryList.get(0).getExpenseId());
+        expenseDO.setId(null);
         expenseMapper.insert(expenseDO.setElderId(elderlyId)
                 .setTenantId(TenantContextHolder.getTenantId())
                 .setCreatedTime(new Date())

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

@@ -263,6 +263,13 @@ public class ElderlyInfoController {
         return success(elderlyInfoService.getCheckInDetail(checkInRecordId));
     }
 
+    @GetMapping("/getCheckInDetailByElderId")
+    @Operation(summary = "根据合同ID获取办理入住详情")
+    @Parameter(name = "contractId", description = "合同ID", required = true, example = "1024")
+    public CommonResult<CheckInRecordDetailRespVO> getCheckInDetailByElderId(@RequestParam("contractId") Long contractId) {
+        return success(elderlyInfoService.getCheckInDetailByElderId(contractId));
+    }
+
 
     @GetMapping("/getGroupTenant")
     @Operation(summary = "获取集团租户")

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

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
 import cn.iocoder.yudao.module.system.api.bpm.vo.CheckInContractReqVO;
 import cn.iocoder.yudao.module.system.api.bpm.vo.CheckInExpenseItemReqVo;
 import cn.iocoder.yudao.module.system.api.bpm.vo.CheckInExpenseSaveReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ExpenseItemDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.RelativesDO;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -39,6 +40,9 @@ public class CheckInRecordDetailRespVO {
     @Schema(description = "长者主键")
     private String elderId;
 
+    @Schema(description = "长者姓名")
+    private String elderName;
+
     @Schema(description = "年龄")
     private Long elderAge;
 
@@ -57,6 +61,12 @@ public class CheckInRecordDetailRespVO {
     @Schema(description = "床位id")
     String bedId;
 
+    @Schema(description = "床位号")
+    private String bedName;
+
+    @Schema(description = "床位类型")
+    private String bedType;
+
     /**
      * 9- 办理入住
      * BpmBusinessTypeEnum
@@ -86,6 +96,9 @@ public class CheckInRecordDetailRespVO {
     @Schema(description = "阶段费用列表")
     private List<CheckInExpenseItemReqVo> stageExpenses;
 
+    @Schema(description = "合同下全部费用明细")
+    private List<ExpenseItemDO> expenseItems;
+
     @Schema(description = "入住时间")
     @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
     private LocalDate checkInTime;

+ 123 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/evaluation/FoodSatisfactionSurveyController.java

@@ -0,0 +1,123 @@
+package cn.iocoder.yudao.module.system.controller.admin.evaluation;
+
+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.context.TenantContextHolder;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveyPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveyRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveySaveReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.excel.FoodSatisfactionSurveyExportExcelVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
+import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
+import cn.iocoder.yudao.module.system.service.evaluation.FoodSatisfactionSurveyService;
+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.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+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("/food-satisfaction-survey")
+@Validated
+public class FoodSatisfactionSurveyController {
+
+    @Resource
+    private FoodSatisfactionSurveyService foodSatisfactionSurveyService;
+    @Resource
+    private TenantMapper tenantMapper;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建膳食满意度调查")
+    @PermitAll
+    public CommonResult<Long> create(@Valid @RequestBody FoodSatisfactionSurveySaveReqVO createReqVO) {
+        createReqVO.setTenantId(Objects.isNull(createReqVO.getTenantId())
+                ? TenantContextHolder.getTenantId() : createReqVO.getTenantId());
+        return success(foodSatisfactionSurveyService.create(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新膳食满意度调查")
+    public CommonResult<Boolean> update(@Valid @RequestBody FoodSatisfactionSurveySaveReqVO updateReqVO) {
+        updateReqVO.setTenantId(Objects.isNull(updateReqVO.getTenantId())
+                ? TenantContextHolder.getTenantId() : updateReqVO.getTenantId());
+        foodSatisfactionSurveyService.update(updateReqVO);
+        return success(Boolean.TRUE);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除膳食满意度调查")
+    @Parameter(name = "id", description = "记录编号", required = true)
+    public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
+        foodSatisfactionSurveyService.delete(id);
+        return success(Boolean.TRUE);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得膳食满意度调查")
+    @Parameter(name = "id", description = "记录编号", required = true, example = "1")
+    public CommonResult<FoodSatisfactionSurveyRespVO> get(@RequestParam("id") Long id) {
+        return success(foodSatisfactionSurveyService.get(id));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得膳食满意度调查分页")
+    public CommonResult<PageResult<FoodSatisfactionSurveyRespVO>> getPage(@Valid FoodSatisfactionSurveyPageReqVO pageReqVO) {
+        pageReqVO.setTenantId(Objects.isNull(pageReqVO.getTenantId())
+                ? TenantContextHolder.getTenantId() : pageReqVO.getTenantId());
+        return success(foodSatisfactionSurveyService.getPage(pageReqVO));
+    }
+
+    @GetMapping("/exportExcel")
+    @Operation(summary = "导出膳食满意度调查 Excel")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportExcel(@Valid FoodSatisfactionSurveyPageReqVO pageReqVO,
+                            HttpServletResponse response) throws IOException {
+        pageReqVO.setTenantId(Objects.isNull(pageReqVO.getTenantId())
+                ? TenantContextHolder.getTenantId() : pageReqVO.getTenantId());
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<FoodSatisfactionSurveyRespVO> list = foodSatisfactionSurveyService.getPage(pageReqVO).getList();
+        Set<Long> tenantIds = list.stream().map(FoodSatisfactionSurveyRespVO::getTenantId)
+                .filter(Objects::nonNull).collect(Collectors.toSet());
+        Map<Long, String> tenantNameMap = tenantIds.isEmpty() ? java.util.Collections.emptyMap()
+                : tenantMapper.selectBatchIds(tenantIds).stream()
+                .filter(Objects::nonNull)
+                .filter(t -> t.getId() != null)
+                .collect(Collectors.toMap(TenantDO::getId, TenantDO::getName, (a, b) -> a));
+
+        List<FoodSatisfactionSurveyExportExcelVO> exportList = new ArrayList<>(list.size());
+        for (FoodSatisfactionSurveyRespVO item : list) {
+            FoodSatisfactionSurveyExportExcelVO excelVO = BeanUtils.toBean(item, FoodSatisfactionSurveyExportExcelVO.class);
+            excelVO.setTenantName(tenantNameMap.get(item.getTenantId()));
+            exportList.add(excelVO);
+        }
+
+        ExcelUtils.write(response, "膳食满意度调查.xls", "数据", FoodSatisfactionSurveyExportExcelVO.class, exportList);
+    }
+}

+ 29 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/evaluation/vo/FoodSatisfactionSurveyPageReqVO.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.system.controller.admin.evaluation.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 FoodSatisfactionSurveyPageReqVO extends PageParam {
+
+    @Schema(description = "机构id", example = "1")
+    private Long tenantId;
+
+    @Schema(description = "角色")
+    private String role;
+
+    @Schema(description = "填写日期范围,格式为 yyyy-MM-dd")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    private LocalDate[] recordDate;
+}

+ 95 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/evaluation/vo/FoodSatisfactionSurveyRespVO.java

@@ -0,0 +1,95 @@
+package cn.iocoder.yudao.module.system.controller.admin.evaluation.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
+
+@Schema(description = "管理后台 - 膳食满意度调查 Response VO")
+@Data
+public class FoodSatisfactionSurveyRespVO {
+
+    @Schema(description = "id", example = "1")
+    private Long id;
+
+    @Schema(description = "角色")
+    private String role;
+
+    @Schema(description = "记录日期")
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    private LocalDate recordDate;
+
+    @Schema(description = "菜品新鲜度")
+    private BigDecimal fresh;
+
+    @Schema(description = "菜品口味(咸淡、口感等)")
+    private BigDecimal taste;
+
+    @Schema(description = "菜品种类丰富度")
+    private BigDecimal variety;
+
+    @Schema(description = "主食多样性(米饭、面食等)")
+    private BigDecimal staple;
+
+    @Schema(description = "汤品 / 饮品口感与温度")
+    private BigDecimal soup;
+
+    @Schema(description = "菜品营养搭配合理性")
+    private BigDecimal nutrition;
+
+    @Schema(description = "餐具清洁程度")
+    private BigDecimal tableware;
+
+    @Schema(description = "用餐环境卫生(桌椅、地面等)")
+    private BigDecimal environment;
+
+    @Schema(description = "工作人员服务态度")
+    private BigDecimal attitude;
+
+    @Schema(description = "菜品供应及时性(未出现长时间断供)")
+    private BigDecimal timely;
+
+    @Schema(description = "菜品分量充足度")
+    private BigDecimal portion;
+
+    @Schema(description = "是否满足软食需求")
+    private String softFood;
+
+    @Schema(description = "是否满足素食需求")
+    private String vegetarian;
+
+    @Schema(description = "对有过敏食材的人群,是否能提供明确的食材标注")
+    private String allergyLabel;
+
+    @Schema(description = "最需要改进的方面")
+    private String improve;
+
+    @Schema(description = "希望新增哪些菜品或服务")
+    private String newDishes;
+
+    @Schema(description = "其他想反馈的内容")
+    private String other;
+
+    @Schema(description = "膳食质量评价总分")
+    private BigDecimal qualityTotal;
+
+    @Schema(description = "膳食服务评价总分")
+    private BigDecimal serviceTotal;
+
+    @Schema(description = "提交人")
+    private String submitter;
+
+    @Schema(description = "机构id")
+    private Long tenantId;
+
+    @Schema(description = "创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+}

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

@@ -0,0 +1,88 @@
+package cn.iocoder.yudao.module.system.controller.admin.evaluation.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Schema(description = "管理后台 - 膳食满意度调查新增/修改 Request VO")
+@Data
+public class FoodSatisfactionSurveySaveReqVO {
+
+    @Schema(description = "id", example = "1")
+    private Long id;
+
+    @Schema(description = "角色", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotBlank(message = "角色不能为空")
+    private String role;
+
+    @Schema(description = "记录日期", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "记录日期不能为空")
+    private LocalDate recordDate;
+
+    @Schema(description = "菜品新鲜度")
+    private BigDecimal fresh;
+
+    @Schema(description = "菜品口味(咸淡、口感等)")
+    private BigDecimal taste;
+
+    @Schema(description = "菜品种类丰富度")
+    private BigDecimal variety;
+
+    @Schema(description = "主食多样性(米饭、面食等)")
+    private BigDecimal staple;
+
+    @Schema(description = "汤品 / 饮品口感与温度")
+    private BigDecimal soup;
+
+    @Schema(description = "菜品营养搭配合理性")
+    private BigDecimal nutrition;
+
+    @Schema(description = "餐具清洁程度")
+    private BigDecimal tableware;
+
+    @Schema(description = "用餐环境卫生(桌椅、地面等)")
+    private BigDecimal environment;
+
+    @Schema(description = "工作人员服务态度")
+    private BigDecimal attitude;
+
+    @Schema(description = "菜品供应及时性(未出现长时间断供)")
+    private BigDecimal timely;
+
+    @Schema(description = "菜品分量充足度")
+    private BigDecimal portion;
+
+    @Schema(description = "是否满足软食需求")
+    private String softFood;
+
+    @Schema(description = "是否满足素食需求")
+    private String vegetarian;
+
+    @Schema(description = "对有过敏食材的人群,是否能提供明确的食材标注")
+    private String allergyLabel;
+
+    @Schema(description = "最需要改进的方面")
+    private String improve;
+
+    @Schema(description = "希望新增哪些菜品或服务")
+    private String newDishes;
+
+    @Schema(description = "其他想反馈的内容")
+    private String other;
+
+    @Schema(description = "膳食质量评价总分")
+    private BigDecimal qualityTotal;
+
+    @Schema(description = "膳食服务评价总分")
+    private BigDecimal serviceTotal;
+
+    @Schema(description = "提交人")
+    private String submitter;
+
+    @Schema(description = "机构id", example = "1")
+    private Long tenantId;
+}

+ 87 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/evaluation/vo/excel/FoodSatisfactionSurveyExportExcelVO.java

@@ -0,0 +1,87 @@
+package cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 膳食满意度调查 Excel 导出 VO
+ */
+@Data
+public class FoodSatisfactionSurveyExportExcelVO {
+
+    @ExcelProperty("机构名称")
+    private String tenantName;
+
+    @ExcelProperty("提交人")
+    private String submitter;
+
+    @ExcelProperty("填写日期")
+    private LocalDate recordDate;
+
+    @ExcelProperty("角色")
+    private String role;
+
+    @ExcelProperty("菜品新鲜度")
+    private BigDecimal fresh;
+
+    @ExcelProperty("菜品口味(咸淡、口感等)")
+    private BigDecimal taste;
+
+    @ExcelProperty("菜品种类丰富度")
+    private BigDecimal variety;
+
+    @ExcelProperty("主食多样性(米饭、面食等)")
+    private BigDecimal staple;
+
+    @ExcelProperty("汤品 / 饮品口感与温度")
+    private BigDecimal soup;
+
+    @ExcelProperty("菜品营养搭配合理性")
+    private BigDecimal nutrition;
+
+    @ExcelProperty("餐具清洁程度")
+    private BigDecimal tableware;
+
+    @ExcelProperty("用餐环境卫生(桌椅、地面等)")
+    private BigDecimal environment;
+
+    @ExcelProperty("工作人员服务态度")
+    private BigDecimal attitude;
+
+    @ExcelProperty("菜品供应及时性(未出现长时间断供)")
+    private BigDecimal timely;
+
+    @ExcelProperty("菜品分量充足度")
+    private BigDecimal portion;
+
+    @ExcelProperty("是否满足软食需求")
+    private String softFood;
+
+    @ExcelProperty("是否满足素食需求")
+    private String vegetarian;
+
+    @ExcelProperty("过敏食材标注是否明确")
+    private String allergyLabel;
+
+    @ExcelProperty("最需要改进的方面")
+    private String improve;
+
+    @ExcelProperty("希望新增哪些菜品或服务")
+    private String newDishes;
+
+    @ExcelProperty("其他反馈内容")
+    private String other;
+
+    @ExcelProperty("膳食质量评价总分")
+    private BigDecimal qualityTotal;
+
+    @ExcelProperty("膳食服务评价总分")
+    private BigDecimal serviceTotal;
+
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+}

+ 111 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/evaluation/FoodSatisfactionSurveyDO.java

@@ -0,0 +1,111 @@
+package cn.iocoder.yudao.module.system.dal.dataobject.evaluation;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableField;
+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.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 膳食满意度调查 DO
+ */
+@TableName("food_satisfaction_survey")
+@KeySequence("food_satisfaction_survey_seq")
+@Data
+@ToString
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class FoodSatisfactionSurveyDO {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** 角色 */
+    private String role;
+
+    /** 记录日期 */
+    private LocalDate recordDate;
+
+    /** 菜品新鲜度 */
+    private BigDecimal fresh;
+
+    /** 菜品口味(咸淡、口感等) */
+    private BigDecimal taste;
+
+    /** 菜品种类丰富度 */
+    private BigDecimal variety;
+
+    /** 主食多样性(米饭、面食等) */
+    private BigDecimal staple;
+
+    /** 汤品 / 饮品口感与温度 */
+    private BigDecimal soup;
+
+    /** 菜品营养搭配合理性 */
+    @TableField("nutrtion")
+    private BigDecimal nutrition;
+
+    /** 餐具清洁程度 */
+    private BigDecimal tableware;
+
+    /** 用餐环境卫生(桌椅、地面等) */
+    private BigDecimal environment;
+
+    /** 工作人员服务态度 */
+    private BigDecimal attitude;
+
+    /** 菜品供应及时性(未出现长时间断供) */
+    private BigDecimal timely;
+
+    /** 菜品分量充足度 */
+    private BigDecimal portion;
+
+    /** 是否满足软食需求 */
+    private String softFood;
+
+    /** 是否满足素食需求 */
+    private String vegetarian;
+
+    /** 对有过敏食材的人群,是否能提供明确的食材标注 */
+    private String allergyLabel;
+
+    /** 最需要改进的方面 */
+    private String improve;
+
+    /** 希望新增哪些菜品或服务 */
+    private String newDishes;
+
+    /** 其他想反馈的内容 */
+    private String other;
+
+    /** 膳食质量评价总分 */
+    private BigDecimal qualityTotal;
+
+    /** 膳食服务评价总分 */
+    private BigDecimal serviceTotal;
+
+    /** 提交人 */
+    private String submitter;
+
+    /** 机构id */
+    private Long tenantId;
+
+    /** 创建时间 */
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    /** 更新时间 */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+}

+ 24 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/evaluation/FoodSatisfactionSurveyMapper.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.system.dal.mysql.evaluation;
+
+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.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveyPageReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.evaluation.FoodSatisfactionSurveyDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 膳食满意度调查 Mapper
+ */
+@Mapper
+public interface FoodSatisfactionSurveyMapper extends BaseMapperX<FoodSatisfactionSurveyDO> {
+
+    default PageResult<FoodSatisfactionSurveyDO> selectPage(FoodSatisfactionSurveyPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<FoodSatisfactionSurveyDO>()
+                .eqIfPresent(FoodSatisfactionSurveyDO::getTenantId, reqVO.getTenantId())
+                .eqIfPresent(FoodSatisfactionSurveyDO::getRole, reqVO.getRole())
+                .betweenIfPresent(FoodSatisfactionSurveyDO::getRecordDate, reqVO.getRecordDate())
+                .orderByDesc(FoodSatisfactionSurveyDO::getRecordDate)
+                .orderByDesc(FoodSatisfactionSurveyDO::getId));
+    }
+}

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

@@ -49,6 +49,8 @@ public interface ElderlyInfoService {
 
     CheckInRecordDetailRespVO getCheckInDetail(Long checkInRecordId);
 
+    CheckInRecordDetailRespVO getCheckInDetailByElderId(Long contractId);
+
     ElderlyHomeRespVO getElderlyInfoHomeData(ElderlyInfoHomeDataReqVO reqVO);
 
     ElderlyHomeRespVO getHomeDataElderlyPortrait(ElderlyInfoHomeDataReqVO reqVO);

+ 127 - 3
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyInfoServiceImpl.java

@@ -163,6 +163,12 @@ public class ElderlyInfoServiceImpl implements ElderlyInfoService {
     @Resource
     private ExpenseOrderItemMapper expenseOrderItemMapper;
 
+    @Resource
+    private ExpenseMapper expenseMapper;
+
+    @Resource
+    private ExpenseItemMapper expenseItemMapper;
+
     @Resource
     private ElderlyHealthRecordMapper elderlyHealthRecordMapper;
 
@@ -871,6 +877,9 @@ public class ElderlyInfoServiceImpl implements ElderlyInfoService {
     @TenantIgnore
     public CheckInRecordDetailRespVO getCheckInDetail(Long id) {
         CheckInRecordDetailRespVO detailRespVO = elderlyInfoMapper.getCheckInDetail(id);
+        if (detailRespVO == null) {
+            return null;
+        }
         List<RelativesDO> relatives = relativesMapper.selectList(new LambdaQueryWrapper<RelativesDO>().eq(RelativesDO::getPeopleId, detailRespVO.getElderId()));
         detailRespVO.setRelativesList(relatives);
         Gson gson = new Gson();
@@ -894,6 +903,124 @@ public class ElderlyInfoServiceImpl implements ElderlyInfoService {
         return detailRespVO;
     }
 
+    @Override
+    @TenantIgnore
+    public CheckInRecordDetailRespVO getCheckInDetailByElderId(Long contractId) {
+        ElderlyContractDO elderlyContract = elderlyContractMapper.selectById(contractId);
+        if (elderlyContract == null) {
+            return null;
+        }
+        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(elderlyContract.getElderId());
+        if (elderlyInfo == null) {
+            return null;
+        }
+
+        CheckInRecordDetailRespVO detailRespVO = new CheckInRecordDetailRespVO();
+        ElderlyCheckInRecordDO checkInRecord = elderlyCheckInRecordMapper.selectOne(new LambdaQueryWrapperX<ElderlyCheckInRecordDO>()
+                .eq(ElderlyCheckInRecordDO::getElderId, elderlyInfo.getId())
+                .eq(ElderlyCheckInRecordDO::getCurrentFlag, 0)
+                .orderByDesc(ElderlyCheckInRecordDO::getCreatedTime)
+                .last("LIMIT 1"));
+        if (checkInRecord != null) {
+            CheckInRecordDetailRespVO currentCheckInDetail = getCheckInDetail(checkInRecord.getId());
+            if (currentCheckInDetail != null) {
+                detailRespVO.setStatus(currentCheckInDetail.getStatus());
+                detailRespVO.setProcessInstanceId(currentCheckInDetail.getProcessInstanceId());
+                detailRespVO.setType(currentCheckInDetail.getType());
+                detailRespVO.setBpmStatus(currentCheckInDetail.getBpmStatus());
+            }
+        }
+        detailRespVO.setElderId(String.valueOf(elderlyInfo.getId()));
+        detailRespVO.setElderName(elderlyInfo.getElderName());
+        detailRespVO.setElderAge(elderlyInfo.getElderAge() == null ? null : elderlyInfo.getElderAge().longValue());
+        detailRespVO.setElderSex(elderlyInfo.getElderSex());
+        detailRespVO.setIdCard(elderlyInfo.getIdCard());
+        detailRespVO.setBedId(elderlyInfo.getBedId() == null ? null : String.valueOf(elderlyInfo.getBedId()));
+        detailRespVO.setBedName(buildService.getFullBedName(elderlyInfo.getId()));
+        detailRespVO.setIsPrivateRoom(elderlyInfo.getIsPrivateRoom());
+        detailRespVO.setSpecialCareNotes(elderlyInfo.getSpecialCareNotes());
+        detailRespVO.setTenantId(elderlyInfo.getTenantId());
+        detailRespVO.setRelativesList(relativesMapper.selectList(new LambdaQueryWrapper<RelativesDO>()
+                .eq(RelativesDO::getPeopleId, elderlyInfo.getId())));
+        detailRespVO.setNurseLevelId(elderlyInfo.getNurseLevelId());
+        NurseLevelDO nurseLevelDO = nurseLevelMapper.selectById(elderlyInfo.getNurseLevelId());
+        detailRespVO.setNurseLevelName(nurseLevelDO == null ? elderlyInfo.getNurseLevelName() : nurseLevelDO.getNurseLevelName());
+        detailRespVO.setCheckInTime(toLocalDate(elderlyContract.getBeginTime()));
+        detailRespVO.setCheckInDeadlineTime(toLocalDate(elderlyContract.getExpireTime()));
+
+        CheckInContractReqVO contractReqVO = new CheckInContractReqVO();
+        BeanUtils.copyProperties(elderlyContract, contractReqVO);
+        detailRespVO.setElderlyContractDO(contractReqVO);
+
+        List<ExpenseDO> expenseList = expenseMapper.selectList(new LambdaQueryWrapperX<ExpenseDO>()
+                .eq(ExpenseDO::getContractId, contractId)
+                .orderByDesc(ExpenseDO::getCreatedTime));
+        if (CollectionUtil.isEmpty(expenseList)) {
+            detailRespVO.setExpenseItems(Collections.emptyList());
+            detailRespVO.setMonthlyExpenses(Collections.emptyList());
+            detailRespVO.setOneTimeExpenses(Collections.emptyList());
+            detailRespVO.setStageExpenses(Collections.emptyList());
+            return detailRespVO;
+        }
+
+        List<Long> expenseIds = expenseList.stream().map(ExpenseDO::getId).collect(Collectors.toList());
+        List<ExpenseItemDO> expenseItems = expenseItemMapper.selectList(new LambdaQueryWrapperX<ExpenseItemDO>()
+                .in(ExpenseItemDO::getExpenseId, expenseIds)
+                .orderByAsc(ExpenseItemDO::getCreateTime)
+                .orderByAsc(ExpenseItemDO::getId));
+
+        detailRespVO.setExpenseItems(expenseItems);
+        detailRespVO.setRemark(expenseList.stream()
+                .map(ExpenseDO::getRemark)
+                .filter(StringUtils::isNotBlank)
+                .findFirst()
+                .orElse(null));
+        detailRespVO.setTotalAmount(expenseItems.stream()
+                .map(this::resolveExpenseAmount)
+                .reduce(BigDecimal.ZERO, BigDecimal::add));
+
+        List<CheckInExpenseItemReqVo> allExpenseItems = expenseItems.stream().map(item -> {
+            CheckInExpenseItemReqVo reqVo = new CheckInExpenseItemReqVo();
+            BeanUtils.copyProperties(item, reqVo);
+            return reqVo;
+        }).collect(Collectors.toList());
+        detailRespVO.setMonthlyExpenses(allExpenseItems.stream()
+                .filter(item -> Objects.equals(item.getIsMonthlyExpense(), 1))
+                .collect(Collectors.toList()));
+        detailRespVO.setOneTimeExpenses(allExpenseItems.stream()
+                .filter(item -> Objects.equals(item.getIsOneTimeFee(), 1) || Objects.equals(item.getIsDeposit(), 1))
+                .collect(Collectors.toList()));
+        detailRespVO.setStageExpenses(allExpenseItems.stream()
+                .filter(item -> !Objects.equals(item.getIsMonthlyExpense(), 1))
+                .filter(item -> !Objects.equals(item.getIsOneTimeFee(), 1))
+                .filter(item -> !Objects.equals(item.getIsDeposit(), 1))
+                .collect(Collectors.toList()));
+        detailRespVO.setBedType(allExpenseItems.stream()
+                .filter(item -> Objects.equals(item.getType(), 1))
+                .map(CheckInExpenseItemReqVo::getItemName)
+                .filter(StringUtils::isNotBlank)
+                .findFirst()
+                .orElse(null));
+        return detailRespVO;
+    }
+
+    private LocalDate toLocalDate(Date date) {
+        return date == null ? null : date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+    }
+
+    private BigDecimal resolveExpenseAmount(ExpenseItemDO expenseItem) {
+        if (expenseItem.getTotalAmount() != null) {
+            return expenseItem.getTotalAmount();
+        }
+        if (expenseItem.getActualAmount() != null) {
+            return expenseItem.getActualAmount();
+        }
+        if (expenseItem.getAmount() != null) {
+            return expenseItem.getAmount();
+        }
+        return BigDecimal.ZERO;
+    }
+
     @Override
     @TenantIgnore
     public ElderlyHomeRespVO getHomeDataElderlyPortrait(ElderlyInfoHomeDataReqVO reqVO) {
@@ -3055,6 +3182,3 @@ public class ElderlyInfoServiceImpl implements ElderlyInfoService {
 
 
 }
-
-
-

+ 22 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/evaluation/FoodSatisfactionSurveyService.java

@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.system.service.evaluation;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveyPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveyRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveySaveReqVO;
+
+/**
+ * 膳食满意度调查 Service
+ */
+public interface FoodSatisfactionSurveyService {
+
+    Long create(FoodSatisfactionSurveySaveReqVO createReqVO);
+
+    void update(FoodSatisfactionSurveySaveReqVO updateReqVO);
+
+    void delete(Long id);
+
+    FoodSatisfactionSurveyRespVO get(Long id);
+
+    PageResult<FoodSatisfactionSurveyRespVO> getPage(FoodSatisfactionSurveyPageReqVO pageReqVO);
+}

+ 78 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/evaluation/FoodSatisfactionSurveyServiceImpl.java

@@ -0,0 +1,78 @@
+package cn.iocoder.yudao.module.system.service.evaluation;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveyPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveyRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.evaluation.vo.FoodSatisfactionSurveySaveReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.evaluation.FoodSatisfactionSurveyDO;
+import cn.iocoder.yudao.module.system.dal.mysql.evaluation.FoodSatisfactionSurveyMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+import java.time.LocalDateTime;
+
+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 FoodSatisfactionSurveyServiceImpl implements FoodSatisfactionSurveyService {
+
+    @Resource
+    private FoodSatisfactionSurveyMapper foodSatisfactionSurveyMapper;
+
+    @Override
+    public Long create(FoodSatisfactionSurveySaveReqVO createReqVO) {
+        FoodSatisfactionSurveyDO survey = BeanUtils.toBean(createReqVO, FoodSatisfactionSurveyDO.class);
+        if (survey.getTenantId() == null) {
+            survey.setTenantId(TenantContextHolder.getTenantId());
+        }
+        survey.setCreateTime(LocalDateTime.now());
+        foodSatisfactionSurveyMapper.insert(survey);
+        return survey.getId();
+    }
+
+    @Override
+    public void update(FoodSatisfactionSurveySaveReqVO updateReqVO) {
+        validateExists(updateReqVO.getId());
+        FoodSatisfactionSurveyDO updateObj = BeanUtils.toBean(updateReqVO, FoodSatisfactionSurveyDO.class);
+        if (updateObj.getTenantId() == null) {
+            updateObj.setTenantId(TenantContextHolder.getTenantId());
+        }
+        foodSatisfactionSurveyMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void delete(Long id) {
+        validateExists(id);
+        foodSatisfactionSurveyMapper.deleteById(id);
+    }
+
+    @Override
+    public FoodSatisfactionSurveyRespVO get(Long id) {
+        FoodSatisfactionSurveyDO survey = foodSatisfactionSurveyMapper.selectById(id);
+        if (survey == null) {
+            throw exception(COMMON_NOT_FOUND);
+        }
+        return BeanUtils.toBean(survey, FoodSatisfactionSurveyRespVO.class);
+    }
+
+    @Override
+    public PageResult<FoodSatisfactionSurveyRespVO> getPage(FoodSatisfactionSurveyPageReqVO pageReqVO) {
+        if (pageReqVO.getTenantId() == null) {
+            pageReqVO.setTenantId(TenantContextHolder.getTenantId());
+        }
+        PageResult<FoodSatisfactionSurveyDO> pageResult = foodSatisfactionSurveyMapper.selectPage(pageReqVO);
+        return BeanUtils.toBean(pageResult, FoodSatisfactionSurveyRespVO.class);
+    }
+
+    private void validateExists(Long id) {
+        if (id == null || foodSatisfactionSurveyMapper.selectById(id) == null) {
+            throw exception(COMMON_NOT_FOUND);
+        }
+    }
+}

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

@@ -247,6 +247,7 @@ yudao:
       - /admin-api/elderly/nursingPlan/getLowFrequencyPlanItemsByFloorId
       - /admin-api/elderly-items-round/batch-create
       - /admin-api/elderly-safe-check/create
+      - /admin-api/food-satisfaction-survey/create
 #      - /admin-api/bpm/check-in-wait/create
     ignore-tables:
       - system_tenant