Procházet zdrojové kódy

新增
1、新增餐饮变更后台批量变更接口
BUGFIX
1、解决办理入住未进行审批但状态已是入住状态的问题

liangwenxuan před 2 týdny
rodič
revize
35359bf4aa
13 změnil soubory, kde provedl 445 přidání a 109 odebrání
  1. 9 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/business/BpmElderlyController.java
  2. 78 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/business/vo/CateringChangeBatchCreateReqVO.java
  3. 4 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/business/BpmElderlApplyService.java
  4. 138 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/business/BpmElderlApplyServiceImpl.java
  5. 6 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
  6. 3 0
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmElderlyChangeApi.java
  7. 31 0
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/bpm/vo/ElderlyCurrentChargeItemRespVO.java
  8. 120 65
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmCheckInApiImpl.java
  9. 7 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmElderlyChangeApiImpl.java
  10. 5 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/ElderlyChangeRecordMapper.java
  11. 3 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ExpenseOrderServiceImpl.java
  12. 1 43
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ExpenseServiceImpl.java
  13. 40 1
      yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/ElderlyChangeRecordMapper.xml

+ 9 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/business/BpmElderlyController.java

@@ -17,6 +17,7 @@ import javax.annotation.Resource;
 import javax.annotation.security.PermitAll;
 import javax.validation.Valid;
 import cn.iocoder.yudao.module.bpm.service.business.BpmElderlApplyService;
+import java.util.Map;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -79,6 +80,14 @@ public class BpmElderlyController {
         return success(elderlApplyService.cateringChangeCreate(getLoginUserId(), createReqVO));
     }
 
+    @PostMapping("/cateringChangeBatchCreate")
+    @PreAuthorize("@ss.hasAnyPermissions('changes:food:add', 'changes:food:relaunch')")
+    @Operation(summary = "批量创建餐饮变更")
+    @TenantIgnore
+    public CommonResult<Map<String, Object>> cateringChangeBatchCreate(@Valid @RequestBody CateringChangeBatchCreateReqVO reqVO) {
+        return success(elderlApplyService.cateringChangeBatchCreate(getLoginUserId(), reqVO));
+    }
+
     @PostMapping("/priceChangeCreate")
     @PreAuthorize("@ss.hasAnyPermissions('price-change:add', 'price-change:relaunch')")
     @Operation(summary = "创建价格变更")

+ 78 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/business/vo/CateringChangeBatchCreateReqVO.java

@@ -0,0 +1,78 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.business.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+
+@Schema(description = "管理后台 - 批量创建餐饮变更 Request VO")
+@Data
+public class CateringChangeBatchCreateReqVO {
+
+    @Schema(description = "院区/机构 tenantId", requiredMode = Schema.RequiredMode.REQUIRED, example = "209")
+    @NotNull(message = "tenantId不能为空")
+    private Long tenantId;
+
+    @Schema(description = "机构类型", example = "1")
+    private Integer orgType = 1;
+
+    @Schema(description = "变更生效日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-05-09")
+    @NotNull(message = "变更生效日期不能为空")
+    private LocalDate changeDate;
+
+    @Schema(description = "变更原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "系统统一变更")
+    @NotEmpty(message = "变更原因不能为空")
+    private String reason;
+
+    @Schema(description = "收费项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "固定费用-餐饮费")
+    @NotEmpty(message = "收费项目名称不能为空")
+    private String categoryName;
+
+    @Schema(description = "变更文件(JSON字符串)", example = "[]")
+    private String changeFiles = "[]";
+
+    @Schema(description = "滞后至月份", example = "2026-01")
+    private String hysteresisMonth;
+
+    @Schema(description = "是否跳过重复申请(同长者同日期)", example = "true")
+    private Boolean skipRepeat = Boolean.TRUE;
+
+    @Schema(description = "是否沿用长者当前折扣信息", example = "true")
+    private Boolean keepDiscount = Boolean.TRUE;
+
+    @Schema(description = "匹配规则与目标餐饮项目列表", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotEmpty(message = "映射列表不能为空")
+    private List<ItemMapping> mappings;
+
+    @Data
+    public static class ItemMapping {
+
+        @Schema(description = "匹配的原费用项目id(优先使用)", example = "1803357950676461384")
+        private Long originalOverheadChargeId;
+
+        @Schema(description = "匹配的原费用项目名称(当 originalOverheadChargeId 为空时使用)", example = "普通食谱")
+        private String originalName;
+
+        @Schema(description = "匹配的原费用实际金额(当 originalOverheadChargeId 为空时使用)", example = "750")
+        private BigDecimal originalActualAmount;
+
+        @Schema(description = "新费用项目id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1803357950676463024")
+        @NotNull(message = "新费用项目id不能为空")
+        private Long expectOverheadChargeId;
+
+        @Schema(description = "新费用项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "普通食谱")
+        @NotEmpty(message = "新费用项目名称不能为空")
+        private String expectName;
+
+        @Schema(description = "新费用金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "900")
+        @NotNull(message = "新费用金额不能为空")
+        private BigDecimal amount;
+
+        @Schema(description = "新费用实际金额(不传则按折扣规则自动计算)", example = "900")
+        private BigDecimal actualAmount;
+    }
+}

+ 4 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/business/BpmElderlApplyService.java

@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.bpm.service.business;
 import cn.iocoder.yudao.module.bpm.controller.admin.business.vo.*;
 import cn.iocoder.yudao.module.system.api.bpm.vo.CheckInCreateReqVO;
 
+import java.util.Map;
+
 /**
  * @Author: jinyd
  * @CreateTime: 2024/8/6  10:55
@@ -29,6 +31,8 @@ public interface BpmElderlApplyService {
 
     Long cateringChangeCreate(Long loginUserId, CateringChangeRecordCreateReqVO createReqVO);
 
+    Map<String, Object> cateringChangeBatchCreate(Long loginUserId, CateringChangeBatchCreateReqVO reqVO);
+
     Long priceChangeCreate(Long loginUserId, PriceChangeRecordCreateReqVO createReqVO);
 
     Long transferChangeCreate(Long loginUserId, TransferChangeRecordCreateReqVO createReqVO);

+ 138 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/business/BpmElderlApplyServiceImpl.java

@@ -21,13 +21,20 @@ import cn.iocoder.yudao.module.system.api.bpm.BpmElderlyChangeApi;
 import com.mzt.logapi.context.LogRecordContext;
 import com.mzt.logapi.starter.annotation.LogRecord;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 
+import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -72,6 +79,10 @@ public class BpmElderlApplyServiceImpl implements BpmElderlApplyService {
     @Resource
     private BpmElderlyExpenseApi elderlyExpenseApi;
 
+    @Resource
+    @Lazy
+    private BpmElderlApplyService self;
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     @LogRecord(type = DMISSION_DISCHARGE_TYPE, subType = DMISSION_ELDER_APPLY_SUB_TYPE, bizNo = "{{#elderId}}",
@@ -254,6 +265,133 @@ public class BpmElderlApplyServiceImpl implements BpmElderlApplyService {
         return bpmBusinessFormService.create(businessFormCreateReqVO);
     }
 
+    @Override
+    @TenantIgnore
+    public Map<String, Object> cateringChangeBatchCreate(Long loginUserId, CateringChangeBatchCreateReqVO reqVO) {
+        Integer identification = 3;
+        List<Long> originalOverheadChargeIds = new ArrayList<>();
+        for (CateringChangeBatchCreateReqVO.ItemMapping mapping : reqVO.getMappings()) {
+            if (mapping.getOriginalOverheadChargeId() != null) {
+                originalOverheadChargeIds.add(mapping.getOriginalOverheadChargeId());
+            }
+        }
+
+        List<ElderlyCurrentChargeItemRespVO> currentItems = elderlyChangeApi.listCurrentChargeItemList(
+                reqVO.getTenantId(), reqVO.getOrgType(), identification, originalOverheadChargeIds.isEmpty() ? null : originalOverheadChargeIds);
+
+        Map<Long, CateringChangeBatchCreateReqVO.ItemMapping> mappingByOriginalId = new LinkedHashMap<>();
+        List<CateringChangeBatchCreateReqVO.ItemMapping> fuzzyMappings = new ArrayList<>();
+        for (CateringChangeBatchCreateReqVO.ItemMapping mapping : reqVO.getMappings()) {
+            if (mapping.getOriginalOverheadChargeId() != null) {
+                mappingByOriginalId.put(mapping.getOriginalOverheadChargeId(), mapping);
+            } else {
+                fuzzyMappings.add(mapping);
+            }
+        }
+
+        List<Long> successProcessIds = new ArrayList<>();
+        List<Long> skippedElderlyIds = new ArrayList<>();
+        Map<Long, String> failedElderlyIds = new LinkedHashMap<>();
+        int matchedCount = 0;
+
+        for (ElderlyCurrentChargeItemRespVO current : currentItems) {
+            CateringChangeBatchCreateReqVO.ItemMapping mapping = mappingByOriginalId.get(current.getOverheadChargeId());
+            if (mapping == null) {
+                for (CateringChangeBatchCreateReqVO.ItemMapping candidate : fuzzyMappings) {
+                    if (candidate.getOriginalName() == null || candidate.getOriginalActualAmount() == null) {
+                        continue;
+                    }
+                    if (!candidate.getOriginalName().equals(current.getItemName())) {
+                        continue;
+                    }
+                    if (current.getActualAmount() == null) {
+                        continue;
+                    }
+                    if (candidate.getOriginalActualAmount().compareTo(current.getActualAmount()) != 0) {
+                        continue;
+                    }
+                    mapping = candidate;
+                    break;
+                }
+            }
+            if (mapping == null) {
+                continue;
+            }
+            matchedCount++;
+
+            if (Boolean.TRUE.equals(reqVO.getSkipRepeat())) {
+                Boolean repeated = elderlyChangeApi.checkRepeat(current.getElderlyId(), reqVO.getChangeDate(),
+                        ChangeTypeEnum.CATERING.getValue(), reqVO.getTenantId());
+                if (Boolean.TRUE.equals(repeated)) {
+                    skippedElderlyIds.add(current.getElderlyId());
+                    continue;
+                }
+            }
+
+            CateringChangeRecordCreateReqVO createReqVO = new CateringChangeRecordCreateReqVO();
+            createReqVO.setElderlyId(current.getElderlyId());
+            createReqVO.setOriginalId(current.getOverheadChargeId());
+            createReqVO.setOriginalName(current.getItemName());
+            createReqVO.setChangeDate(reqVO.getChangeDate());
+            createReqVO.setExpectId(mapping.getExpectOverheadChargeId());
+            createReqVO.setExpectName(mapping.getExpectName());
+            createReqVO.setCategoryName(reqVO.getCategoryName());
+            createReqVO.setOverheadChargeId(current.getOverheadChargeId());
+            createReqVO.setExpectOverheadChargeId(mapping.getExpectOverheadChargeId());
+            createReqVO.setAmount(mapping.getAmount());
+
+            BigDecimal discountAmount = null;
+            Integer isDiscount = 0;
+            String discount = null;
+            if (Boolean.TRUE.equals(reqVO.getKeepDiscount())) {
+                discountAmount = current.getDiscountAmount();
+                isDiscount = current.getIsDiscount() == null ? 0 : current.getIsDiscount();
+                discount = current.getDiscount();
+            }
+            createReqVO.setIsDiscount(isDiscount);
+            createReqVO.setDiscountAmount(discountAmount);
+            createReqVO.setDiscount(discount);
+
+            BigDecimal actualAmount = mapping.getActualAmount();
+            if (actualAmount == null) {
+                if (Boolean.TRUE.equals(reqVO.getKeepDiscount()) && discountAmount != null) {
+                    actualAmount = mapping.getAmount().subtract(discountAmount);
+                } else {
+                    actualAmount = mapping.getAmount();
+                }
+            }
+            createReqVO.setActualAmount(actualAmount);
+
+            createReqVO.setChangeFiles(StringUtil.isEmpty(reqVO.getChangeFiles()) ? "[]" : reqVO.getChangeFiles());
+            createReqVO.setReason(reqVO.getReason());
+            createReqVO.setType(BpmBusinessTypeEnum.CATERING_CHANGE.getValue());
+            createReqVO.setTenantId(reqVO.getTenantId());
+            createReqVO.setOriginalAmount(current.getActualAmount());
+            createReqVO.setHysteresisMonth(reqVO.getHysteresisMonth());
+
+            try {
+                Long processId = self.cateringChangeCreate(loginUserId, createReqVO);
+                successProcessIds.add(processId);
+            } catch (Exception e) {
+                failedElderlyIds.put(current.getElderlyId(), Objects.toString(e.getMessage(), "ERROR"));
+            }
+        }
+
+        Map<String, Object> result = new LinkedHashMap<>();
+        result.put("tenantId", reqVO.getTenantId());
+        result.put("orgType", reqVO.getOrgType());
+        result.put("changeDate", reqVO.getChangeDate());
+        result.put("matchedCount", matchedCount);
+        result.put("successCount", successProcessIds.size());
+        result.put("successProcessIds", successProcessIds);
+        result.put("skippedCount", skippedElderlyIds.size());
+        result.put("skippedElderlyIds", skippedElderlyIds);
+        result.put("failedCount", failedElderlyIds.size());
+        result.put("failedElderlyIds", failedElderlyIds);
+        result.put("totalCurrentCateringCount", currentItems.size());
+        return result;
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     @LogRecord(type = ELDER_PRICE_CHANGE_TYPE, subType = ELDER_PRICE_CHANGE_SUB_TYPE, bizNo = "{{#createReqVO.elderlyId}}",

+ 6 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java

@@ -34,6 +34,7 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
 import cn.iocoder.yudao.module.bpm.dal.mysql.business.BpmBusinessFormMapper;
 import cn.iocoder.yudao.module.bpm.dal.redis.BpmProcessIdRedisDAO;
+import cn.iocoder.yudao.module.bpm.enums.BpmBusinessTypeEnum;
 import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
 import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
 import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeTypeEnum;
@@ -825,6 +826,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
         updateProcessInstanceCancel(cancelReqVO.getId(),
                 BpmReasonEnum.CANCEL_PROCESS_INSTANCE_BY_START_USER.format(cancelReqVO.getReason()));
 
+        BpmBusinessFormDO businessFormDO = businessFormService.selectOneByProcessInstanceId(instance.getProcessInstanceId());
+        if (businessFormDO != null && Objects.equals(businessFormDO.getType(), BpmBusinessTypeEnum.CHECK_IN.getValue())) {
+            checkInApi.unbindBedOnCancel(businessFormDO.getBusinessId());
+        }
+
         // 取消完成全部消息
         notifyMessageSendApi.updateSelfMessageStatus(instance.getProcessInstanceId(), "", null, null,
                 BpmMessageStatusEnum.COMPLETE.getValue(), null,  Boolean.FALSE);

+ 3 - 0
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmElderlyChangeApi.java

@@ -32,6 +32,9 @@ public interface BpmElderlyChangeApi {
 
     Boolean checkRepeat(Long elderlyId, LocalDate changeDate, Integer changeType, Long tenantId);
 
+    List<ElderlyCurrentChargeItemRespVO> listCurrentChargeItemList(Long tenantId, Integer orgType,
+                                                                   Integer identification, List<Long> overheadChargeIds);
+
     PageResult<NurseChangeRecordRespVO> getNurseChangeRecordPage(ChangeRecordPageReqApiVO apiVO);
 
     PageResult<CateringChangeRecordRespVO> getCateringChangeRecordPage(ChangeRecordPageReqApiVO apiVO);

+ 31 - 0
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/bpm/vo/ElderlyCurrentChargeItemRespVO.java

@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.system.api.bpm.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class ElderlyCurrentChargeItemRespVO {
+
+    private Long elderlyId;
+
+    private String elderlyName;
+
+    private String idCard;
+
+    private Long tenantId;
+
+    private Long expenseItemId;
+
+    private Long overheadChargeId;
+
+    private String itemName;
+
+    private BigDecimal actualAmount;
+
+    private BigDecimal discountAmount;
+
+    private Integer isDiscount;
+
+    private String discount;
+}

+ 120 - 65
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmCheckInApiImpl.java

@@ -159,7 +159,7 @@ public class BpmCheckInApiImpl implements BpmCheckInApi {
         insertBO.setCheckInTime(elderlyContractDO.getBeginTime());
         insertBO.setCreatedTime(new Date());
         insertBO.setElderId(createReqVO.getElderlyId());
-        insertBO.setStatus(2);
+        insertBO.setStatus(1);
         insertBO.setAssociateId(checkInApplyDO.getId());
         insertBO.setCurrentFlag(0);
         insertBO.setTenantId(createReqVO.getTenantId());
@@ -215,6 +215,11 @@ public class BpmCheckInApiImpl implements BpmCheckInApi {
         Long expenseOrderId = expenseService.createExpense(expenseSaveReqVO);
 
         ElderlyInfoDO elderlyInfoDO = elderlyInfoMapper.selectById(checkInApplyDO.getElderlyId());
+        if (elderlyInfoDO != null && expenseSaveReqVO.getInStatusType() != null) {
+            elderlyInfoDO.setInStatusType(expenseSaveReqVO.getInStatusType());
+            elderlyInfoMapper.updateById(elderlyInfoDO);
+        }
+        applyCheckInStatusOnApproval(elderlyCheckInRecordDO, checkInApplyDO, elderlyInfoDO, expenseSaveReqVO.getTenantId());
 
         notifyMessageSendApi.updateMessageByCodeAndPkMessage(BpmMessageEnum.CHECK_IN_HANDLE.getTemplateCode(), elderlyInfoDO.getId());
 
@@ -300,6 +305,55 @@ public class BpmCheckInApiImpl implements BpmCheckInApi {
         return 0;
     }
 
+    @Override
+    @TenantIgnore
+    public Integer unbindBedOnCancel(Long businessId) {
+        ElderlyCheckInRecordDO checkInRecord = recordMapper.selectById(businessId);
+        if (checkInRecord == null || checkInRecord.getAssociateId() == null) {
+            return 0;
+        }
+        CheckInApplyDO checkInApplyDO = checkInApplyMapper.selectById(checkInRecord.getAssociateId());
+        if (checkInApplyDO == null || checkInApplyDO.getBedId() == null) {
+            return 0;
+        }
+        unlockBed(checkInApplyDO.getBedId(), checkInRecord.getTenantId());
+        return 0;
+    }
+
+    private void applyCheckInStatusOnApproval(ElderlyCheckInRecordDO checkInRecordDO, CheckInApplyDO checkInApplyDO,
+                                              ElderlyInfoDO elderlyInfoDO, Long tenantId) {
+        if (checkInRecordDO == null || checkInApplyDO == null || elderlyInfoDO == null) {
+            return;
+        }
+        if (checkInApplyDO.getBedId() != null) {
+            BuildBedDO bedDO = buildBedMapper.selectById(checkInApplyDO.getBedId());
+            if (bedDO != null) {
+                elderlyInfoDO.setBedId(bedDO.getId());
+                elderlyInfoDO.setBedName(bedDO.getBedName());
+                elderlyInfoDO.setRoomId(bedDO.getRoomId());
+                elderlyInfoDO.setFloorId(bedDO.getFloorId());
+                elderlyInfoDO.setBuildId(bedDO.getBuildId());
+                lockBed(bedDO.getId(), tenantId);
+            }
+        }
+        elderlyInfoDO.setInStatus(1);
+        elderlyInfoDO.setCheckInTime(checkInApplyDO.getCheckInTime());
+        elderlyInfoDO.setNurseLevelId(checkInApplyDO.getNurseLevelId());
+        elderlyInfoDO.setIsPrivateRoom(checkInApplyDO.getIsPrivateRoom());
+        elderlyInfoDO.setSpecialCareNotes(checkInApplyDO.getSpecialCareNotes());
+        if (checkInApplyDO.getNurseLevelId() != null) {
+            NurseLevelDO nurseLevelDO = nurseLevelMapper.selectById(checkInApplyDO.getNurseLevelId());
+            elderlyInfoDO.setNurseLevelName(nurseLevelDO == null ? null : nurseLevelDO.getNurseLevelName());
+        }
+        elderlyInfoMapper.updateById(elderlyInfoDO);
+
+        checkInRecordDO.setStatus(2);
+        if (checkInApplyDO.getCheckInTime() != null) {
+            checkInRecordDO.setCheckInTime(checkInApplyDO.getCheckInTime());
+        }
+        recordMapper.updateById(checkInRecordDO);
+    }
+
     @Override
     public PageResult<CheckInRecordRespVO> getProcessInstanceCheckInPage(CheckInApiPageReqVO pageReqVO) {
         Page<CheckInRecordRespVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
@@ -320,75 +374,76 @@ public class BpmCheckInApiImpl implements BpmCheckInApi {
     @TenantIgnore
     public Integer bindBedByType(CheckInCreateReqVO createReqVO, Integer queryType) {
         CheckInExpenseSaveReqVO expenseBO = createReqVO.getExpenseBO();
-
-        // 绑定床位信息
-        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(expenseBO.getElderId());
-        Long bedId = elderlyInfo.getBedId();
-        BuildBedDO bedDO = buildBedMapper.selectById(expenseBO.getBedId());
-        // queryType 0:绑定 1:解绑
-        if (0 == queryType) {
-            if (bedDO != null) {
-                elderlyInfo.setRoomId(bedDO.getRoomId());
-                elderlyInfo.setFloorId(bedDO.getFloorId());
-                elderlyInfo.setBuildId(bedDO.getBuildId());
-
-                bedDO.setStatus(1);
-                buildBedMapper.updateById(bedDO);
-
-                BuildRoomDO roomDO = buildRoomMapper.selectById(bedDO.getRoomId());
-                // TODO 为什么不在楼栋房间表增加床位数量字段,状态增加满员,更加精确形容房间的状态
-                roomDO.setStatus(1);
-                buildRoomMapper.updateById(roomDO);
-            }
-        } else {
-            // 解绑之前的床位
-            BuildBedDO historyBedDO  = buildBedMapper.selectById(bedId);
-            if (null != historyBedDO) {
-                // 释放之前的床位
-                historyBedDO.setStatus(0);
-                buildBedMapper.updateById(historyBedDO);
-                BuildRoomDO historyRoomDO = buildRoomMapper.selectById(historyBedDO.getRoomId());
-                List<BuildBedDO> buildBedDOS = buildBedMapper.selectList(new LambdaQueryWrapperX<BuildBedDO>()
-                        .eq(BuildBedDO::getRoomId, bedDO.getRoomId())
-                        .eq(BuildBedDO::getTenantId, createReqVO.getTenantId()));
-                if(null != buildBedDOS && buildBedDOS.size() == 1) {
-                    historyRoomDO.setStatus(0);
-                    buildRoomMapper.updateById(historyRoomDO);
-                }
-            }
-            if (null != bedDO) {
-                elderlyInfo.setRoomId(bedDO.getRoomId());
-                elderlyInfo.setFloorId(bedDO.getFloorId());
-                elderlyInfo.setBuildId(bedDO.getBuildId());
-
-                bedDO.setStatus(1);
-                buildBedMapper.updateById(bedDO);
-                BuildRoomDO roomDO = buildRoomMapper.selectById(bedDO.getRoomId());
-                roomDO.setStatus(1);
-                buildRoomMapper.updateById(roomDO);
-
+        if (expenseBO == null || expenseBO.getElderId() == null || expenseBO.getBedId() == null) {
+            return 0;
+        }
+        Long tenantId = createReqVO.getTenantId();
+        Long elderId = expenseBO.getElderId();
+        Long newBedId = expenseBO.getBedId();
+
+        if (Integer.valueOf(1).equals(queryType)) {
+            Long historyBedId = getLatestProcessBedId(elderId, tenantId, newBedId);
+            if (historyBedId != null) {
+                unlockBed(historyBedId, tenantId);
             }
-
         }
-        elderlyInfo.setInStatus(1);
-        elderlyInfo.setBedId(expenseBO.getBedId());
-        elderlyInfo.setCheckInTime(expenseBO.getCheckInTime());
-        elderlyInfo.setNurseLevelId(expenseBO.getNurseLevelId());
-        elderlyInfo.setIsPrivateRoom(expenseBO.getIsPrivateRoom());
-        NurseLevelDO nurseLevelDO = nurseLevelMapper.selectById(expenseBO.getNurseLevelId());
-        elderlyInfo.setNurseLevelName(nurseLevelDO == null ? null : nurseLevelDO.getNurseLevelName());
-        elderlyInfoMapper.updateById(elderlyInfo);
-        ElderlyCheckInRecordDO elderlyCheckInRecord = recordMapper.selectOne(new LambdaQueryWrapperX<ElderlyCheckInRecordDO>()
-                .eq(ElderlyCheckInRecordDO::getElderId, elderlyInfo.getId())
-                .eq(ElderlyCheckInRecordDO::getTenantId, createReqVO.getTenantId())
+        lockBed(newBedId, tenantId);
+        return 0;
+    }
+
+    private Long getLatestProcessBedId(Long elderId, Long tenantId, Long excludeBedId) {
+        ElderlyCheckInRecordDO historyRecord = recordMapper.selectOne(new LambdaQueryWrapperX<ElderlyCheckInRecordDO>()
+                .eq(ElderlyCheckInRecordDO::getElderId, elderId)
+                .eqIfPresent(ElderlyCheckInRecordDO::getTenantId, tenantId)
+                .eq(ElderlyCheckInRecordDO::getCurrentFlag, 1)
                 .orderByDesc(ElderlyCheckInRecordDO::getCreatedTime)
                 .last("LIMIT 1"));
-        if (elderlyCheckInRecord != null) {
-            elderlyCheckInRecord.setStatus(2); //修改状态为已入住
-            elderlyCheckInRecord.setCheckInTime(expenseBO.getCheckInTime());
-            recordMapper.updateById(elderlyCheckInRecord);
+        if (historyRecord == null || historyRecord.getAssociateId() == null) {
+            return null;
+        }
+        CheckInApplyDO historyApply = checkInApplyMapper.selectById(historyRecord.getAssociateId());
+        if (historyApply == null || historyApply.getBedId() == null) {
+            return null;
         }
+        if (excludeBedId != null && excludeBedId.equals(historyApply.getBedId())) {
+            return null;
+        }
+        return historyApply.getBedId();
+    }
+
+    private void unlockBed(Long bedId, Long tenantId) {
+        BuildBedDO bedDO = buildBedMapper.selectById(bedId);
+        if (bedDO == null) {
+            return;
+        }
+        bedDO.setStatus(0);
+        buildBedMapper.updateById(bedDO);
+        updateRoomStatus(bedDO.getRoomId(), tenantId);
+    }
 
-        return null;
+    private void lockBed(Long bedId, Long tenantId) {
+        BuildBedDO bedDO = buildBedMapper.selectById(bedId);
+        if (bedDO == null) {
+            return;
+        }
+        bedDO.setStatus(1);
+        buildBedMapper.updateById(bedDO);
+        updateRoomStatus(bedDO.getRoomId(), tenantId);
+    }
+
+    private void updateRoomStatus(Long roomId, Long tenantId) {
+        if (roomId == null) {
+            return;
+        }
+        BuildRoomDO roomDO = buildRoomMapper.selectById(roomId);
+        if (roomDO == null) {
+            return;
+        }
+        Long occupiedCount = buildBedMapper.selectCount(new LambdaQueryWrapperX<BuildBedDO>()
+                .eq(BuildBedDO::getRoomId, roomId)
+                .eqIfPresent(BuildBedDO::getTenantId, tenantId)
+                .ne(BuildBedDO::getStatus, 0));
+        roomDO.setStatus(occupiedCount != null && occupiedCount > 0 ? 1 : 0);
+        buildRoomMapper.updateById(roomDO);
     }
 }

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

@@ -251,6 +251,13 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
         return checkResult;
     }
 
+    @Override
+    @TenantIgnore
+    public List<ElderlyCurrentChargeItemRespVO> listCurrentChargeItemList(Long tenantId, Integer orgType, Integer identification,
+                                                                          List<Long> overheadChargeIds) {
+        return changeRecordMapper.selectCurrentChargeItemList(tenantId, orgType, identification, overheadChargeIds);
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     @TenantIgnore

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

@@ -72,6 +72,11 @@ public interface ElderlyChangeRecordMapper extends BaseMapperX<ElderlyChangeReco
                                                   @Param("pageVO") ElderlyInfoPageReqVO pageVO,
                                                   @Param("elderId") Long elderId);
 
+    List<ElderlyCurrentChargeItemRespVO> selectCurrentChargeItemList(@Param("tenantId") Long tenantId,
+                                                                     @Param("orgType") Integer orgType,
+                                                                     @Param("identification") Integer identification,
+                                                                     @Param("overheadChargeIds") List<Long> overheadChargeIds);
+
     List<NurseChangeRecordRespVO> selectNurseListPage(Page<NurseChangeRecordRespVO> page,
                                                       @Param("pageVO") ChangeRecordPageReqApiVO pageReqVO);
 

+ 3 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ExpenseOrderServiceImpl.java

@@ -3934,6 +3934,9 @@ public class ExpenseOrderServiceImpl implements ExpenseOrderService {
             vouchersDO.setOrderNumber(orderNumber);
             vouchersDOList.add(vouchersDO);
         }
+        if(vouchersDOList.isEmpty()){
+            return;
+        }
         elderlyConsumerVouchersMapper.updateBatch(vouchersDOList);
     }
 }

+ 1 - 43
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ExpenseServiceImpl.java

@@ -152,49 +152,7 @@ public class ExpenseServiceImpl implements ExpenseService {
         }
 
         Long elderId = createReqVO.getElderId();
-        // TODO 绑定床位信息
         ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(createReqVO.getElderId());
-        if (elderlyInfo != null && createReqVO.getInStatusType() != null) {
-            elderlyInfo.setInStatusType(createReqVO.getInStatusType());
-            elderlyInfoMapper.updateById(elderlyInfo);
-        }
-//        if (elderlyInfo != null) {
-//            BuildBedDO bedDO = buildBedMapper.selectById(createReqVO.getBedId());
-//            if (bedDO != null) {
-//                elderlyInfo.setRoomId(bedDO.getRoomId());
-//                elderlyInfo.setFloorId(bedDO.getFloorId());
-//                elderlyInfo.setBuildId(bedDO.getBuildId());
-//
-//                bedDO.setStatus(1);
-//                buildBedMapper.updateById(bedDO);
-//
-//                BuildRoomDO roomDO = buildRoomMapper.selectById(bedDO.getRoomId());
-//                roomDO.setStatus(1);
-//                buildRoomMapper.updateById(roomDO);
-//            }
-//            elderlyInfo.setInStatus(1);
-//            elderlyInfo.setBedId(createReqVO.getBedId());
-//            elderlyInfo.setCheckInTime(createReqVO.getCheckInTime());
-//            elderlyInfo.setNurseLevelId(createReqVO.getNurseLevelId());
-//            elderlyInfo.setIsPrivateRoom(createReqVO.getIsPrivateRoom());
-//            NurseLevelDO nurseLevelDO = nurseLevelMapper.selectById(createReqVO.getNurseLevelId());
-//            elderlyInfo.setNurseLevelName(nurseLevelDO == null ? null : nurseLevelDO.getNurseLevelName());
-//            elderlyInfoMapper.updateById(elderlyInfo);
-//
-//            ElderlyCheckInRecordDO elderlyCheckInRecord = elderlyCheckInRecordMapper.selectOne(new LambdaQueryWrapperX<ElderlyCheckInRecordDO>()
-//                    .eq(ElderlyCheckInRecordDO::getElderId, elderlyInfo.getId())
-//                    .orderByDesc(ElderlyCheckInRecordDO::getCreatedTime)
-//                    .last("LIMIT 1"));
-//            if (elderlyCheckInRecord != null) {
-//                elderlyCheckInRecord.setStatus(2); //修改状态为已入住
-//                elderlyCheckInRecord.setCheckInTime(createReqVO.getCheckInTime());
-//                elderlyCheckInRecordMapper.updateById(elderlyCheckInRecord);
-//            }
-//
-//            LogRecordContext.putVariable("elderId", elderlyInfo.getId());
-//            LogRecordContext.putVariable("elderName", elderlyInfo.getElderName());
-//
-//        }
 
         //生成入院缴费账单
         LocalDate date = createReqVO.getCheckInTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
@@ -207,7 +165,7 @@ public class ExpenseServiceImpl implements ExpenseService {
         expenseBill.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
         expenseBill.setElderId(createReqVO.getElderId());
         expenseBill.setBillOrderNumber("E" + RandomUtil.randomNumbers(16));
-        expenseBill.setType(elderlyInfo.getInStatusType() == 2 ? 3 : 1);
+        expenseBill.setType(createReqVO.getInStatusType() == 2 ? 3 : 1);
         expenseBill.setTenantId(createReqVO.getTenantId());
         expenseOrderMapper.insert(expenseBill);
 

+ 40 - 1
yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/ElderlyChangeRecordMapper.xml

@@ -246,6 +246,45 @@
         order by ei.update_time desc
     </select>
 
+    <select id="selectCurrentChargeItemList" resultType="cn.iocoder.yudao.module.system.api.bpm.vo.ElderlyCurrentChargeItemRespVO">
+        SELECT
+            ei.id AS elderlyId,
+            ei.elder_name AS elderlyName,
+            ei.id_card AS idCard,
+            ei.tenant_id AS tenantId,
+            eei.id AS expenseItemId,
+            eei.item_id AS overheadChargeId,
+            eei.item_name AS itemName,
+            eei.actual_amount AS actualAmount,
+            eei.discount_amount AS discountAmount,
+            eei.is_discount AS isDiscount,
+            eei.discount AS discount
+        FROM
+            elderly_info ei
+                INNER JOIN elderly_expense ee ON ei.id = ee.elder_id
+                INNER JOIN elderly_expense_item eei ON eei.expense_id = ee.id
+                INNER JOIN sys_charge_category scc ON scc.id = eei.item_category_id
+        WHERE
+            ei.in_status = 1
+            AND ee.created_time = (SELECT MAX(ee2.created_time) FROM elderly_expense ee2 WHERE ee2.elder_id = ei.id)
+            <if test="identification != null">
+                AND scc.identification = #{identification}
+            </if>
+            <if test="tenantId != null">
+                AND ei.tenant_id = #{tenantId}
+            </if>
+            <if test="orgType != null">
+                AND ei.org_type = #{orgType}
+            </if>
+            <if test="overheadChargeIds != null and overheadChargeIds.size() > 0">
+                AND eei.item_id in
+                <foreach item="id" collection="overheadChargeIds" open="(" separator="," close=")">
+                    #{id}
+                </foreach>
+            </if>
+        order by ei.update_time desc
+    </select>
+
     <select id="selectNurseListPage" resultType="cn.iocoder.yudao.module.system.api.bpm.vo.NurseChangeRecordRespVO">
         SELECT
             ecr.id,
@@ -797,4 +836,4 @@
           AND t.tenant_id = #{tenantId}
     </select>
 
-</mapper>
+</mapper>