Java vue 养老系统源码详解:入住核算单 live-check 缴费入账与预交金收据实践

Java养老系统源码详解:入住核算单 live-check 缴费入账与预交金收据实践

在线演示 :管理端后台

标签:#Java #Spring Boot #MyBatis #养老系统 #入住核算单 #care_bill_payment #changeBiz


1. 入住核算单与缴费入账

合同审批通过后 费用管理 · 入住核算单 出现一行 paymentType=入住;前台录入预交金、押金实缴,后端 CareBillPaymentServiceImpl.pay 调 CareAccountService.changeBiz,bizType=BILL_PAYMENT,并带 care_pay_way 交易方式。

开户在合同生效时 getOrOpen 已完成;核算单只负责应缴实缴对齐,不重复开户。

图1 入住核算单 · 押金/预交金/一次性分项

图2 缴费后账户流水

2. CareBillPaymentDO 与状态常量

复制代码
private static final int TYPE_CHECKIN = 1;
private static final int STATUS_PENDING = 0;
private static final int STATUS_PARTIAL = 1;
private static final int STATUS_DONE = 2;

private static final int WALLET_BALANCE = 1;
private static final int WALLET_DEPOSIT = 2;
private static final int CHANGE_RECHARGE = 1;

@TableName("care_bill_payment")
public class CareBillPaymentDO extends CareOrgBaseDO {
    private Long olderId;
    private Long checkinId;
    private Integer paymentType;
    private BigDecimal depositDue;
    private BigDecimal advanceDue;
    private BigDecimal amountDue;
    private BigDecimal advancePaid;
    private BigDecimal depositPaid;
    private Integer status;
}

3. generateCheckinFromApply(审批通过生成单据)

复制代码
public Long generateCheckinFromApply(CareContractDO contract, CareContractSubmitCheckinReqVO reqVO) {
    CareBillPaymentDO exists = careBillPaymentMapper.selectByCheckinIdAndType(
            contract.getCheckinId(), TYPE_CHECKIN);
    if (exists != null) {
        return exists.getId();
    }
    payment.setPaymentType(TYPE_CHECKIN);
    payment.setTitle("入住核算单");
    payment.setDepositDue(depositDue);
    payment.setAdvanceDue(advanceDue);
    careBillPaymentMapper.insert(payment);
    return payment.getId();
}

4. pay:预交金/押金分钱包 + 缴清扣一次性费

复制代码
public List<Long> pay(CareBillPaymentPayReqVO reqVO) {
    if (advance.compareTo(BigDecimal.ZERO) > 0) {
        flowIds.add(careAccountService.changeBiz(
                exists.getOlderId(), WALLET_BALANCE, CHANGE_RECHARGE,
                advance, "a5", "BILL_PAYMENT", exists.getId(), payRemark, reqVO.getPayWay()));
    }
    if (deposit.compareTo(BigDecimal.ZERO) > 0) {
        flowIds.add(careAccountService.changeBiz(
                exists.getOlderId(), WALLET_DEPOSIT, CHANGE_RECHARGE,
                deposit, "b1", "BILL_PAYMENT", exists.getId(), payRemark, reqVO.getPayWay()));
    }
    if (becomingDone && Objects.equals(exists.getPaymentType(), TYPE_CHECKIN)) {
        flowIds.addAll(deductCheckinOneTimeFees(exists, reqVO.getPayWay()));
    }
}
  • advanceOk && depositOk:分项达标才 STATUS_DONE;被褥/其他一次性费在缴清后从预交金扣。

5. Controller 与 curl

复制代码
@RestController
@RequestMapping("/care/bill-payment")
public class CareBillPaymentController {
    @PostMapping("/pay")
    public CommonResult<List<Long>> pay(@Valid @RequestBody CareBillPaymentPayReqVO reqVO) {
        return success(careBillPaymentService.pay(reqVO));
    }
}

curl -X POST "http://localhost:48080/admin-api/care/bill-payment/pay" \
  -H "Authorization: Bearer {token}" \
  -H "tenant-id: 123" \
  -H "Content-Type: application/json" \
  -d '{"id":6001,"advancePaid":5000,"depositPaid":2000,"payWay":"1"}'

补充:缴清顺序与一次性费用

pay 里要先 updateById 把核算单标为已缴清 ,再扣被褥等一次性费;否则 deductCheckinOneTimeFees 仍被「入住核算未缴清」拦住(社区版已按此顺序修复)。

图3 费用管理 · 入住核算单筛选

图4 合同生效后才会生成 TYPE_CHECKIN 核算单

复制代码
// CareBillPaymentServiceImpl.pay(逻辑顺序)
careBillPaymentMapper.updateById(doneUpdate); // status=STATUS_DONE
if (becomingDone && Objects.equals(exists.getPaymentType(), TYPE_CHECKIN)) {
    flowIds.addAll(deductCheckinOneTimeFees(exists, reqVO.getPayWay()));
    deductCheckinMonthBillFullIfNeeded(exists, reqVO.getPayWay());
}
钱包 changeType 典型科目
预交金 充值 a5
押金 充值 b1
预交金 扣费 a1/a2/a3 一次性
复制代码
curl -G "http://localhost:48080/admin-api/care/bill-payment/page"   -H "Authorization: Bearer {token}" -H "tenant-id: 123"   --data-urlencode "paymentType=1" --data-urlencode "status=0"

图5 缴清后首月整单扣费依赖计费设置(见 30 篇)

6. 踩坑

  • 重复 pay:STATUS_DONE 抛 BILL_PAYMENT_STATUS_ERROR。
  • 只传 amount 老字段:整笔当预交金,新前端应拆 advancePaid/depositPaid。
  • 缴清但未扣一次性费:检查 becomingDone 与 feeItems 是否入库。
  • tenant-id:流水按租户隔离,联调必带。

补充:日志与排错顺序

  1. 浏览器 Network 看 /admin-api 返回 code/msg。

  2. IDEA 断点 Service 入口,确认 tenant-id 与业务 id。

  3. 查库 status 与界面一致(勿只改 checkin 不改 bed)。

  4. 定时任务看 infra_job 日志与 @TenantJob 租户上下文。

    curl -X POST -H "tenant-id: 123" -H "Content-Type: application/json"
    -d "{"phone":"13900001001","password":"123456","accountType":2}"
    http://127.0.0.1:8086/app-api/care/family-auth/login

联调:application-local 与 tenant-id

本地 zhijian-server 联调时,管理端请求统一带头:

复制代码
yudao:
  tenant:
    enable: true
spring:
  profiles:
    active: local

curl -H "Authorization: Bearer {token}" -H "tenant-id: 123" \
  "http://localhost:48080/admin-api/care/..."

403 先查角色是否勾选菜单按钮权限;401 查 token 是否过期。多园环境 rootDeptId 与登录部门一致,否则计费/报表可能看到空列表。

模块路径(Maven)

模块 典型包路径
institution zhijian-module-institution/.../service/
hub zhijian-module-hub/.../service/hub/
bi zhijian-module-bi/.../service/bi/
monitor zhijian-module-monitor/.../
community zhijian-module-community/.../
medical zhijian-module-medical/.../

交付裁剪时 zhijian-server/pom.xml 注释未购业态 JAR,并执行 care_maven_delivery_menu_crop.sql 隐藏菜单,避免「有菜单无 API」。

与 hub 中台衔接

老人主档 care_older 在 hub;机构业务 care_checkin / care_contract 在 institution。中台档案页不存 bed_id,床态以 care_bed.status 为准(见 24 篇)。跨模块只通过 olderId、SPI Bridge 或 REST,不在 hub 里直接 join institution 大表。

演示站对照

在线演示:管理端后台 --- 登录后左侧菜单与源码 @PreAuthorize 权限码一致;改 SQL 菜单后需重新登录刷新路由。


Gitee 社区版源码 :https://gitee.com/xinzexingjian-data_0/older_care

相关推荐
Sand(ContextGate)2 小时前
从开发者调试工具到消费级 App:一个 AI 电商导购项目的 C 端改造与 6 个连环踩坑实录
开发语言·人工智能·python·ai·langchain
外收内放2 小时前
数据分析(DataFrame与series)
python·学习·数据分析
共饮一杯无2 小时前
LiveKit本地录制落盘路径排查与修复实践
java·go·livekit
StevenLdh2 小时前
第八期 · 情绪闯关挑战盒:一个「无惩罚」成就系统的数据建模
java·微信小程序
Wang's Blog2 小时前
Java 项目实战: 交友项目 - 入门案例:编写 Dubbo 服务消费者
java·dubbo·交友
IT研究室3 小时前
最新计算机毕业设计选题推荐-基于spring boot的教育学习平台-网站-文档指导-Java-springboot
java·spring boot·课程设计
亚林瓜子3 小时前
Spring Boot 集成 ip2region 离线 IP 库实战指南
java·spring boot·后端·ip·ip2region
Want5953 小时前
Python太极八卦图
开发语言·python
川石课堂软件测试3 小时前
自动化测试|持续集成Git使用详解
git·python·jmeter·mysql·ci/cd·容器·kubernetes