Files
Home-Care/居家上门服务系统_可执行实现方案_补齐可开工版.md
comclib 4a2eb09606
Some checks failed
CI / backend (push) Has been cancelled
CI / website (push) Has been cancelled
chore: 文档整理 — 移动至 docs/ 目录, 更新 IMPLEMENTATION_PLAN.md
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:52:03 +08:00

77 KiB
Raw Blame History

居家上门服务系统 — 可执行实现方案(补齐可开工版)

生成日期2026-05-15 补齐版本V1.1 生产可交付补强版 基于V2.0 工程落地增强版 + V2.1 行业经验增强版 + V2.2 边界限制增强版 项目状态:全新仓库,从零搭建

本版结论可以进入实现但必须按本补齐版执行。本文已补齐幂等表、任务执行日志、Outbox 并发安全、delivery 最小闭环、支付退款、异常监管、完整 OpenAPI 契约、E2E/并发/失败注入测试、灰度回滚与上线验收门槛。


0. 补齐版执行口径

本补齐版用于替代原执行方案中不完整或容易产生歧义的部分。若本文后续章节与原章节存在冲突,以本补齐版中的以下规则为准:

  1. delivery 最小闭环必须进入 MVP 第一批,不能整体后移。
  2. 幂等不能只依赖 Redis 或状态流转表,必须新增 hss_idempotency_records
  3. 定时任务必须有执行日志,必须新增 hss_job_execution_logs
  4. Outbox 必须具备并发抢占、重试、死信能力,不能只做简单轮询。
  5. 支付、退款、冲正必须独立建模,不能只放在结算表字段里。
  6. 异常处理、监管整改、投诉反馈必须独立闭环,不能只在工单备注里处理。
  7. 状态机必须拆为规则判断与动作编排两层,不能只返回目标状态。
  8. OpenAPI 契约必须覆盖消费者端、管理端、delivery 端和内部任务接口
  9. 测试必须覆盖并发、重复提交、Outbox 失败、支付重复回调、任务重跑、弱网补传
  10. 上线采用 roll-forward + feature flag + dry-run + shadow 模式,不能依赖直接删字段或强回滚。

1. 需求与约束摘要

内容
任务类型 新接口 / 新能力开发(全新系统)
目标 实现居家上门服务全链路闭环系统:需求受理 → 评估定级 → 方案制定 → 派单调度 → 上门执行 → 过程监管 → 验收反馈 → 结算归档
硬边界 Spring Boot / Java 17+、PostgreSQL、Redis、MQTT(通知)、对象存储(文件)、RESTful+action、OpenAPI 3.1、hss_表前缀、Outbox通知、四层状态机、幂等写、前端只传动作不传状态、敏感数据授权脱敏审计
范围 全部模块 + delivery 端小程序

2. 代码依据

本项目为全新仓库,无现有后端代码。以下为架构文档依据:

依据文件 路径 职责
V2.0 工程落地增强版 docs/ architecture/居家上门服务闭环流程文档_V2工程落地增强版.md 业务闭环流程、四层状态机、数据模型、调度算法、通知设计、合规安全、结算对账
V2.1 行业经验增强版 docs/ architecture/居家上门服务闭环流程文档_V2.1_行业经验增强版.md 美团三层调度、ETA预测、VRPTW建模、delivery智能助手、运力运营中心、主数据平台、SRE稳定性
V2.2 边界限制增强版 /home/akoo/居家服务/居家上门服务闭环流程文档_V2.2_边界限制增强版.md 12条硬约束、技术栈锁定、DDL边界、接口风格、部署环境、协作边界

3. DDL 依据

当前仓库无 db/init.sqldb/update.sql。以下设计基于 V2.0 文档 4.1 节数据域划分(第 939-958 行),结合 V2.2 第 16.3 节 DDL 边界约束。

数据域 设计表名hss_前缀 来源
申请域 hss_service_applications V2.0 §4.1
用户画像域 hss_patient_profiles V2.0 §4.1
评估域 hss_assessment_taskshss_assessment_reports V2.0 §4.1
异议域 hss_objections V2.0 §4.2
方案域 hss_service_planshss_service_plan_itemshss_plan_versions V2.0 §4.1
计划域 hss_service_schedules V2.0 §4.1
工单域 hss_work_ordershss_work_order_items V2.0 §4.1
执行域 hss_checkinshss_execution_recordshss_evidence_files V2.0 §4.1
异常域 hss_exceptionshss_exception_actions V2.0 §4.1
监管域 hss_spot_checkshss_violationshss_corrections V2.0 §4.1
验收域 hss_acceptanceshss_complaints V2.0 §4.1
结算域 hss_settlementshss_settlement_itemshss_paymentshss_refunds V2.0 §4.1
归档域 hss_ledgershss_archive_files V2.0 §4.1
通知域 hss_notification_outboxhss_notification_receipts V2.0 §7.2
审计域 hss_audit_logshss_state_transitions V2.0 §3.6、§8.4
合规域 hss_consent_recordshss_data_access_logs V2.0 §8.2
调度域V2.1扩展) hss_service_gridshss_grid_capacity_dailyhss_staff_skill_capacityhss_capacity_forecastshss_capacity_alerts V2.1 §15.2.1
主数据域V2.1扩展) hss_md_orgshss_md_staffhss_md_qualificationshss_md_service_itemshss_md_regionshss_md_price_rules V2.1 §15.7

4. 改动范围清单

全部为新增文件。

路径 增/删/改 摘要
pom.xml Maven 构建配置Spring Boot 3.x + Java 17
src/main/java/com/meizhou/hss/ 根包目录
src/main/java/.../common/ 公共模块:响应体、异常、工具类、幂等注解、审计切面
src/main/java/.../config/ Spring 配置Security、Redis、MQTT、对象存储、定时任务、OpenAPI
src/main/java/.../statemachine/ 四层状态机引擎:申请、方案、工单、结算
src/main/java/.../module/application/ 申请域controller/service/repository/entity/dto
src/main/java/.../module/assessment/ 评估域controller/service/repository/entity/dto
src/main/java/.../module/plan/ 方案域controller/service/repository/entity/dto
src/main/java/.../module/schedule/ 计划与调度域
src/main/java/.../module/workorder/ 工单域
src/main/java/.../module/execution/ 执行域:签到、执行记录、证据链
src/main/java/.../module/exception/ 异常域:异常上报与处理
src/main/java/.../module/supervision/ 监管域:抽查、违规、整改
src/main/java/.../module/acceptance/ 验收域:验收、评价、投诉
src/main/java/.../module/settlement/ 结算域:结算、支付、退款
src/main/java/.../module/archive/ 归档域:台账、归档文件
src/main/java/.../module/notification/ 通知域Outbox 与回执
src/main/java/.../module/audit/ 审计域:审计日志、状态流转
src/main/java/.../module/compliance/ 合规域:授权同意、数据访问日志
src/main/java/.../module/masterdata/ 主数据域:机构、人员、资质、服务项目、区域、价格
src/main/java/.../module/capacity/ 运力域:服务网格、容量、预测
src/main/resources/db/migration/ Flyway 迁移脚本
src/main/resources/application.yml 主配置
src/test/java/.../ 单元测试与集成测试
delivery-miniapp/ delivery 端小程序uni-app

5. 方案概述

5.1 分层架构

┌──────────────────────────────────────────────┐
│  Controller 层REST + action-style REST    │
│  - 参数校验Spring Validation              │
│  - 幂等拦截Idempotency-Key                │
│  - 权限注解(@PreAuthorize                  │
│  - OpenAPI 注解SpringDoc                  │
└──────────────────┬───────────────────────────┘
                   │
┌──────────────────▼───────────────────────────┐
│  Service 层(业务编排)                       │
│  - 状态机调用(不跳过状态检查)               │
│  - 事务边界(@Transactional                 │
│  - Outbox 写入(同事务)                      │
│  - 审计日志写入                              │
└──────────────────┬───────────────────────────┘
                   │
┌──────────────────▼───────────────────────────┐
│  Repository 层(数据访问)                    │
│  - MyBatis-Plus BaseMapper                    │
│  - 自定义 SQL复杂查询/统计)                │
│  - 乐观锁 version 字段                        │
└──────────────────┬───────────────────────────┘
                   │
┌──────────────────▼───────────────────────────┐
│  Domain 层(领域对象)                        │
│  - Entity映射表                           │
│  - DTO / VO / Request / Response             │
│  - 状态枚举                                   │
│  - 业务异常                                   │
└──────────────────────────────────────────────┘

5.2 核心数据流

POST /applications       → 创建申请DRAFT
POST /applications/{id}/submit → 提交申请PENDING_ACCEPTANCE
POST /applications/{id}/accept → 受理通过PENDING_ASSESSMENT
POST /assessments/{id}/assign  → 派发评估ASSESSING
POST /assessments/{id}/submit  → 提交评估ASSESSMENT_PASSED
POST /plans                 → 创建方案PLAN_DRAFT
POST /plans/{id}/submit     → 提交签署PLAN_PENDING_SIGN
POST /plans/{id}/sign       → 签署通过PLAN_EFFECTIVE
POST /schedules/{id}/generate → 生成服务计划
POST /work-orders/{id}/dispatch → 派单ORDER_ASSIGNED
POST /work-orders/{id}/accept  → 接单ORDER_ACCEPTED
POST /work-orders/{id}/check-in → 签到ORDER_CHECKED_IN
POST /work-orders/{id}/start   → 开始服务ORDER_IN_SERVICE
POST /execution-records     → 逐项记录执行
POST /work-orders/{id}/finish → 完成服务ORDER_COMPLETED
POST /acceptances           → 发起验收ACCEPTANCE_PENDING
POST /acceptances/{id}/confirm → 验收通过ACCEPTED
POST /settlements/{id}/generate → 生成结算单
POST /settlements/{id}/approve → 审核通过
POST /settlements/{id}/pay  → 支付完成SETTLEMENT_PAID
POST /settlements/{id}/archive → 归档ARCHIVED

5.3 异常流

任何非终态 → POST /{entity}/{id}/cancel → CANCELLED需原因
评估中 → POST /assessments/{id}/object → REVIEWING → 维持/重评
方案待签署 → POST /plans/{id}/reject → PLAN_REJECTED → 重新编制
工单已派单 → POST /work-orders/{id}/reassign → 改派
工单服务中 → POST /work-orders/{id}/report-exception → ORDER_EXCEPTION → 协调/改派/关闭
验收拒绝 → POST /acceptances/{id}/reject → 创建问题处理单
结算不通过 → POST /settlements/{id}/return → 退回修改

6. 代码级修改说明(核心)

6.1 项目初始化

文件pom.xml(新增)

当前逻辑:不存在。 拟议改动:创建 Maven 父 POM管理所有模块依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
    </parent>
    <groupId>com.meizhou</groupId>
    <artifactId>hss-home-service</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>HSS Home Service</name>
    <properties>
        <java.version>17</java.version>
        <mybatis-plus.version>3.5.6</mybatis-plus.version>
        <springdoc.version>2.5.0</springdoc.version>
        <flyway.version>10.11.0</flyway.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-database-postgresql</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>${springdoc.version}</version>
        </dependency>
        <!-- 测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

6.2 公共模块

目录src/main/java/com/meizhou/hss/common/(新增)

6.2.1 统一响应体

文件ApiResponse.java(新增)

当前逻辑:不存在。 拟议改动:所有接口统一使用此响应格式。

// 新增
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ApiResponse<T> {
    private int code;          // 200 成功
    private String message;
    private T data;
    private String requestId;  // UUID
    private long timestamp;    // System.currentTimeMillis()

    public static <T> ApiResponse<T> ok(T data) { ... }
    public static <T> ApiResponse<T> fail(int code, String message) { ... }
}

6.2.2 幂等拦截

文件@Idempotent.java + IdempotentAspect.java(新增)

当前逻辑:不存在。 拟议改动:基于 Redis 实现 request_id 幂等。相同 requestId + action + entityId 在 TTL 内重复提交返回首次结果。

// 新增注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {
    String prefix() default "idempotent";
    long ttlSeconds() default 300;
}

// 新增切面
@Aspect
@Component
public class IdempotentAspect {
    @Around("@annotation(idempotent)")
    public Object around(ProceedingJoinPoint pjp, Idempotent idempotent) {
        // 从请求头获取 Idempotency-Key
        // 拼接 key = prefix + ":" + idempotencyKey
        // Redis SET NX EX成功则执行失败则返回缓存结果
    }
}

6.2.3 审计字段基类

文件BaseEntity.java(新增)

// 新增 - 所有 hss_ 表 Entity 继承此类
@Data
public abstract class BaseEntity {
    @TableId(type = IdType.AUTO)
    private Long id;
    private Long tenantId;
    private Long orgId;
    private String status;
    private Integer version;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
    private Long createdBy;
    private Long updatedBy;
    @TableLogic
    private Integer deleted;  // 0 正常, 1 已删除
}

6.3 状态机引擎

目录src/main/java/com/meizhou/hss/statemachine/(新增)

文件清单

文件 职责
StateMachine.java 通用状态机接口:transition(entity, action, context) → targetState
StateMachineConfig.java 状态转换规则配置(从 YAML/DB 加载)
TransitionRule.java 单条转换规则fromStatus + action + role → toStatus + constraints
ApplicationStateMachine.java 申请状态机实现
PlanStateMachine.java 方案状态机实现
WorkOrderStateMachine.java 工单状态机实现
SettlementStateMachine.java 结算状态机实现
StateTransitionException.java 非法状态转换异常

当前逻辑:不存在。 拟议改动:基于 V2.0 文档 §3.2~3.5 的状态转换表实现。

// 新增 - TransitionRule
public record TransitionRule(
    String entityType,    // application / plan / work_order / settlement
    String fromStatus,
    String action,        // submit / accept / reject / check-in / finish / approve / ...
    String requiredRole,  // 允许执行此动作的角色
    String toStatus,
    List<String> constraints  // 约束条件:如 "hasAssessmentReport"、"amountMatched"
) {}

// 新增 - StateMachine 核心方法
public class StateMachine {
    // 校验转换是否合法
    public boolean canTransition(String entityType, String fromStatus,
                                  String action, String role);
    // 执行转换(不通过抛 StateTransitionException
    public String transition(String entityType, String fromStatus,
                              String action, String role, Map<String, Object> context);
    // 记录状态流转到 hss_state_transitions
    private void recordTransition(...);
}

状态转换规则初始化(基于文档 §3.2~3.5,部分示例):

// 新增 - 申请状态机规则
rules.add(new TransitionRule("application", "DRAFT", "submit", "APPLICANT",
    "PENDING_ACCEPTANCE", List.of("materialsComplete")));
rules.add(new TransitionRule("application", "PENDING_ACCEPTANCE", "accept", "RECEPTIONIST",
    "PENDING_ASSESSMENT", List.of("ageCheck", "qualificationCheck", "duplicateCheck")));
rules.add(new TransitionRule("application", "PENDING_ACCEPTANCE", "return", "RECEPTIONIST",
    "RETURNED", List.of("returnReasonRequired")));
// ... 等全部规则

6.4 申请域模块

目录src/main/java/com/meizhou/hss/module/application/

文件清单

文件 职责
entity/ServiceApplicationEntity.java 映射 hss_service_applications
dto/ApplicationCreateRequest.java 创建申请请求 DTO
dto/ApplicationSubmitRequest.java 提交申请请求 DTO
dto/ApplicationResponse.java 申请响应 DTO
dto/ApplicationListQuery.java 列表查询参数
repository/ServiceApplicationMapper.java MyBatis-Plus Mapper
service/ApplicationService.java 业务逻辑
service/ApplicationValidationService.java 自动校验(材料完整性、资格、重复申请)
controller/ApplicationController.java REST 接口

当前逻辑:不存在。

拟议改动

ApplicationController.java

// 新增
@RestController
@RequestMapping("/api/hss/applications")
@Tag(name = "服务申请")
public class ApplicationController {

    @PostMapping
    @Idempotent(prefix = "app:create")
    public ApiResponse<ApplicationResponse> create(
            @Valid @RequestBody ApplicationCreateRequest req) {
        // Service: 校验 → 创建 DRAFT 状态申请 → 记录状态流转
    }

    @PostMapping("/{id}/submit")
    @Idempotent(prefix = "app:submit")
    public ApiResponse<ApplicationResponse> submit(
            @PathVariable Long id, @Valid @RequestBody ApplicationSubmitRequest req) {
        // Service: 状态机 DRAFT→PENDING_ACCEPTANCE → 写 Outbox 通知受理员
    }

    @PostMapping("/{id}/accept")
    @Idempotent(prefix = "app:accept")
    @PreAuthorize("hasRole('RECEPTIONIST')")
    public ApiResponse<ApplicationResponse> accept(@PathVariable Long id) {
        // Service: 校验(材料+资格+重复)→ 状态机 PENDING_ACCEPTANCE→PENDING_ASSESSMENT
    }

    @PostMapping("/{id}/return")
    @Idempotent(prefix = "app:return")
    @PreAuthorize("hasRole('RECEPTIONIST')")
    public ApiResponse<ApplicationResponse> returnApplication(
            @PathVariable Long id, @Valid @RequestBody ReturnRequest req) {
        // 约束:必须填写退回原因
    }

    @PostMapping("/{id}/cancel")
    @Idempotent(prefix = "app:cancel")
    public ApiResponse<ApplicationResponse> cancel(@PathVariable Long id) {
        // 约束:申请人本人或授权家属
    }

    @GetMapping
    public ApiResponse<Page<ApplicationResponse>> list(ApplicationListQuery query) {
        // 数据范围:按 tenant_id、org_id、角色过滤
    }

    @GetMapping("/{id}")
    public ApiResponse<ApplicationResponse> getById(@PathVariable Long id) {
        // 脱敏:非授权角色隐藏完整地址、电话
    }
}

:其余模块(评估、方案、调度、工单、执行、异常、监管、验收、结算、归档、通知、审计、合规、主数据、运力)的代码结构遵循相同模式,此处为避免文档过度膨胀,仅输出申请域作为样板。完整代码在实施阶段逐模块编写。

6.5 通知 Outbox 模块

目录src/main/java/com/meizhou/hss/module/notification/

关键设计:

// 新增 - 通知创建(在业务事务内调用)
@Service
public class NotificationService {
    // 与业务在同一事务中写入 Outbox
    @Transactional
    public void createNotification(Long entityId, String entityType,
                                    String channel, String template, Map<String, Object> params) {
        NotificationOutboxEntity outbox = new NotificationOutboxEntity();
        outbox.setEntityId(entityId);
        outbox.setChannel(channel); // MQTT / WECHAT / SMS
        outbox.setStatus("CREATED");
        outbox.setRequestId(IdempotencyContext.getRequestId());
        outboxMapper.insert(outbox);
    }
}

// 新增 - 定时任务:扫描 Outbox 并异步发送
@Component
public class NotificationSender {
    @Scheduled(fixedDelay = 2000) // 每2秒扫描
    public void sendPending() {
        // SELECT * FROM hss_notification_outbox WHERE status='CREATED' LIMIT 100
        // 发送 → 更新 status=SENT → 记录 receipt
        // 失败 → status=FAILED, retry_count+1
    }
}

6.6 审计模块

目录src/main/java/com/meizhou/hss/module/audit/

// 新增 - AOP 切面自动记录审计
@Aspect
@Component
public class AuditAspect {
    @Around("@annotation(auditable)")
    public Object around(ProceedingJoinPoint pjp, Auditable auditable) {
        // 记录操作人、时间、IP、设备、操作类型、业务对象ID、前后值
    }
}

// 新增 - 状态流转记录(状态机内部调用)
// 写入 hss_state_transitions
// entity_type, entity_id, from_status, action, to_status,
// operator_id, operator_role, reason, request_id, created_at

6.7 调度算法模块

目录src/main/java/com/meizhou/hss/module/schedule/algorithm/

// 新增 - 两阶段调度
@Service
public class DispatchAlgorithm {

    // 阶段1硬约束过滤
    public List<StaffCandidate> hardFilter(List<Staff> allStaff, WorkOrder order) {
        return allStaff.stream()
            .filter(s -> s.getStatus() == StaffStatus.ACTIVE)
            .filter(s -> s.hasQualification(order.getRequiredSkills()))
            .filter(s -> s.getRegion().contains(order.getServiceAddress().getRegion()))
            .filter(s -> !hasTimeConflict(s, order))
            .filter(s -> !s.isBlacklisted())
            .filter(s -> s.getTodayOrderCount() < s.getMaxDailyOrders())
            .toList();
    }

    // 阶段2软约束评分
    public List<ScoredStaff> scoreAndRank(List<StaffCandidate> candidates, WorkOrder order) {
        // score = distance * 0.25 + skill * 0.25 + workload * 0.20
        //       + rating * 0.15 + response * 0.10 + familiarity * 0.05
        // 返回 Top5附解释
    }
}

7. 接口设计方案(任务类型=1 强制)

7.1 核心接口清单

按主链路阶段组织,以下为核心接口设计。

7.1.1 服务申请接口组

接口1创建服务申请

接口名称 创建服务申请
接口地址 /api/hss/applications
请求方式 POST
接口描述 服务对象/家属提交服务申请,创建后状态为 DRAFT
参数名 类型 是否必填 说明
patientId string 服务对象ID
serviceType string 服务类型枚举HOME_CARE / REHABILITATION / BATH_ASSIST / ASSESSMENT
channel string 申请渠道APP / WECHAT / PHONE / COMMUNITY / HOSPITAL
contactName string 联系人姓名
contactPhone string 联系人电话
address string 服务地址
regionCode string 区域编码
notes string 备注说明
attachmentIds array 附件ID列表
字段路径 类型 示例 说明
code int 200 状态码
success boolean true 是否成功
message string 申请创建成功 响应消息
data.id string 1001 申请ID
data.status string DRAFT 申请状态
data.createdAt string 2026-05-15T10:30:00 创建时间

请求示例:

{
  "patientId": "2001",
  "serviceType": "HOME_CARE",
  "channel": "WECHAT",
  "contactName": "张三",
  "contactPhone": "138****5678",
  "address": "梅江区金山街道XX小区3栋201",
  "regionCode": "441402001",
  "notes": "老人独居,需要日常护理",
  "attachmentIds": ["att_001", "att_002"]
}

返回示例:

{
  "code": 200,
  "message": "申请创建成功",
  "data": {
    "id": "1001",
    "status": "DRAFT",
    "createdAt": "2026-05-15T10:30:00"
  },
  "requestId": "req-uuid-abc123",
  "timestamp": 1715747400000
}

接口2提交服务申请

接口名称 提交服务申请
接口地址 /api/hss/applications/{id}/submit
请求方式 POST
接口描述 将草稿状态申请提交为待受理,触发自动校验
参数名 类型 是否必填 说明
id string 路径参数申请ID
字段路径 类型 示例 说明
code int 200 状态码
data.status string PENDING_ACCEPTANCE 新状态
data.validationResult.passed boolean true 自动校验结果

接口3受理通过

接口名称 受理通过
接口地址 /api/hss/applications/{id}/accept
请求方式 POST
接口描述 受理员审核通过,申请进入待评估状态
参数名 类型 是否必填 说明
id string 路径参数申请ID
reason string 审核备注

接口4受理退回

接口名称 受理退回
接口地址 /api/hss/applications/{id}/return
请求方式 POST
接口描述 受理员退回申请,需填写退回原因
参数名 类型 是否必填 说明
id string 路径参数
reason string 退回原因(必填)

7.1.2 工单执行接口组

接口5GPS 签到

接口名称 GPS签到
接口地址 /api/hss/work-orders/{id}/check-in
请求方式 POST
接口描述 服务人员在服务地址200米内签到需GPS+照片+对象确认
参数名 类型 是否必填 说明
id string 工单ID
latitude number 纬度
longitude number 经度
photoFileId string 现场照片文件ID
patientConfirmed boolean 服务对象是否确认
patientSignatureId string 对象签名文件ID
字段路径 类型 示例 说明
code int 200 状态码
data.status string ORDER_CHECKED_IN 新状态
data.distance number 85.5 签到位置距服务地址距离(米)
data.checkinTime string 2026-05-15T09:05:00 签到时间

请求示例:

{
  "latitude": 24.2878,
  "longitude": 116.1271,
  "photoFileId": "file_checkin_001",
  "patientConfirmed": true,
  "patientSignatureId": "sig_001"
}

返回示例:

{
  "code": 200,
  "message": "签到成功",
  "data": {
    "id": "5001",
    "status": "ORDER_CHECKED_IN",
    "distance": 85.5,
    "checkinTime": "2026-05-15T09:05:00"
  },
  "requestId": "req-uuid-def456",
  "timestamp": 1715747700000
}

接口6服务完成提交

接口名称 服务完成提交
接口地址 /api/hss/work-orders/{id}/finish
请求方式 POST
接口描述 服务人员完成所有必做项目后提交,工单进入已完成状态
参数名 类型 是否必填 说明
id string 工单ID
executionRecords array 项目执行记录列表
executionRecords[].planItemId string 方案项目ID
executionRecords[].status string COMPLETED / PARTIAL / NOT_COMPLETED / SKIPPED / USER_REFUSED
executionRecords[].actualStartTime string 实际开始时间
executionRecords[].actualEndTime string 实际结束时间
executionRecords[].evidenceFileIds array 证据文件ID列表
executionRecords[].notes string 执行备注
signOffLatitude number 签退纬度
signOffLongitude number 签退经度
serviceSummary string 服务总结

7.1.3 结算接口组

接口7生成结算单

接口名称 生成结算单
接口地址 /api/hss/settlements/generate
请求方式 POST
接口描述 基于已验收工单生成结算单,自动汇总金额与抵扣
参数名 类型 是否必填 说明
workOrderIds array 已验收工单ID列表
periodStart string 结算周期开始日期
periodEnd string 结算周期结束日期
字段路径 类型 示例 说明
data.id string 7001 结算单ID
data.totalAmount number 1200.00 总金额
data.insuranceDeduction number 800.00 长护险抵扣
data.selfPayAmount number 400.00 自费金额
data.items array [...] 结算明细

7.2 接口契约约定

  • 所有写接口必须带 Idempotency-Key 请求头
  • 所有分页接口参数:page默认1size默认20最大100sort(如 createdAt,desc
  • 状态动作接口路径格式:POST /api/hss/{resource}/{id}/{action}
  • 资源 CRUDGET/POST/PUT/DELETE /api/hss/{resource}/{id}
  • 统一错误响应:
{
  "code": 40001,
  "message": "参数校验失败",
  "details": [
    {"field": "contactPhone", "message": "联系电话格式不正确"}
  ],
  "requestId": "req-uuid-err123"
}

7.3 错误码规划

错误码范围 含义
200 成功
40001-40099 参数校验错误
40101-40199 认证/授权错误
40301-40399 权限不足
40401-40499 资源不存在
40901-40999 状态冲突(非法状态转换)
40910-40919 幂等冲突(重复提交)
42201-42299 业务规则校验失败
50001-50099 服务器内部错误
50301-50399 依赖服务不可用

8. 数据库与迁移计划

8.1 DDL 变更明细

迁移脚本位于 src/main/resources/db/migration/,采用 Flyway 管理。

V1__baseline.sql初始基线

核心表结构(部分示例):

-- ==========================================
-- 基线迁移 V1创建居家服务核心业务表
-- ==========================================

-- 1. 申请域
CREATE TABLE hss_service_applications (
    id              BIGSERIAL PRIMARY KEY,
    tenant_id       BIGINT NOT NULL,
    org_id          BIGINT NOT NULL,
    patient_id      BIGINT NOT NULL,
    service_type    VARCHAR(32) NOT NULL,      -- HOME_CARE / REHABILITATION / BATH_ASSIST / ASSESSMENT
    channel         VARCHAR(32) NOT NULL,       -- APP / WECHAT / PHONE / COMMUNITY / HOSPITAL
    contact_name    VARCHAR(64) NOT NULL,
    contact_phone   VARCHAR(20) NOT NULL,
    address         TEXT NOT NULL,
    region_code     VARCHAR(20) NOT NULL,
    status          VARCHAR(32) NOT NULL DEFAULT 'DRAFT',
    notes           TEXT,
    version         INTEGER NOT NULL DEFAULT 0,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT,
    updated_by      BIGINT,
    deleted         SMALLINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_hss_app_status ON hss_service_applications(status);
CREATE INDEX idx_hss_app_patient ON hss_service_applications(patient_id);
CREATE INDEX idx_hss_app_created ON hss_service_applications(created_at);

-- 2. 评估域
CREATE TABLE hss_assessment_tasks (
    id              BIGSERIAL PRIMARY KEY,
    tenant_id       BIGINT NOT NULL,
    org_id          BIGINT NOT NULL,
    application_id  BIGINT NOT NULL REFERENCES hss_service_applications(id),
    assessor_id     BIGINT,
    status          VARCHAR(32) NOT NULL DEFAULT 'PENDING_ASSIGNMENT',
    -- 评估结果快照
    care_level      VARCHAR(16),               -- LEVEL_1 ~ LEVEL_5
    risk_level      VARCHAR(16),               -- LOW / MEDIUM / HIGH / CRITICAL
    report_content  JSONB,
    version         INTEGER NOT NULL DEFAULT 0,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT,
    updated_by      BIGINT,
    deleted         SMALLINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_hss_at_status ON hss_assessment_tasks(status);
CREATE INDEX idx_hss_at_app ON hss_assessment_tasks(application_id);
CREATE INDEX idx_hss_at_assessor ON hss_assessment_tasks(assessor_id);

CREATE TABLE hss_assessment_reports (
    id              BIGSERIAL PRIMARY KEY,
    task_id         BIGINT NOT NULL REFERENCES hss_assessment_tasks(id),
    version         INTEGER NOT NULL DEFAULT 1,
    content         JSONB NOT NULL,            -- 评估指标详情
    conclusion      TEXT,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT
);

-- 3. 方案域
CREATE TABLE hss_service_plans (
    id              BIGSERIAL PRIMARY KEY,
    tenant_id       BIGINT NOT NULL,
    org_id          BIGINT NOT NULL,
    application_id  BIGINT NOT NULL,
    assessment_task_id BIGINT NOT NULL,
    status          VARCHAR(32) NOT NULL DEFAULT 'PLAN_DRAFT',
    version_number  INTEGER NOT NULL DEFAULT 1,
    total_amount    DECIMAL(12,2),             -- 方案总金额
    insurance_deduction DECIMAL(12,2),         -- 长护险抵扣
    self_pay_amount DECIMAL(12,2),             -- 自费金额
    signed_at       TIMESTAMP,
    signed_by       BIGINT,
    effective_at    TIMESTAMP,
    terminated_at   TIMESTAMP,
    version         INTEGER NOT NULL DEFAULT 0,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT,
    updated_by      BIGINT,
    deleted         SMALLINT NOT NULL DEFAULT 0
);

CREATE TABLE hss_service_plan_items (
    id              BIGSERIAL PRIMARY KEY,
    plan_id         BIGINT NOT NULL REFERENCES hss_service_plans(id),
    service_item_id BIGINT NOT NULL,           -- 引用主数据服务项目
    item_name       VARCHAR(128) NOT NULL,     -- 版本化快照
    unit_price      DECIMAL(10,2) NOT NULL,    -- 版本化快照
    frequency       INTEGER NOT NULL,          -- 服务频次
    standard_duration INTEGER,                 -- 标准服务时长(分钟)
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE TABLE hss_plan_versions (
    id              BIGSERIAL PRIMARY KEY,
    plan_id         BIGINT NOT NULL,
    version_number  INTEGER NOT NULL,
    snapshot_data   JSONB NOT NULL,            -- 完整方案快照
    change_reason   TEXT,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT
);

-- 4. 服务计划域
CREATE TABLE hss_service_schedules (
    id              BIGSERIAL PRIMARY KEY,
    tenant_id       BIGINT NOT NULL,
    plan_id         BIGINT NOT NULL REFERENCES hss_service_plans(id),
    scheduled_date  DATE NOT NULL,
    time_window_start TIME,                    -- 预约时间窗开始
    time_window_end   TIME,                    -- 预约时间窗结束
    status          VARCHAR(32) NOT NULL DEFAULT 'SCHEDULED',
    version         INTEGER NOT NULL DEFAULT 0,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_hss_ss_date ON hss_service_schedules(scheduled_date);
CREATE INDEX idx_hss_ss_plan ON hss_service_schedules(plan_id);

-- 5. 工单域
CREATE TABLE hss_work_orders (
    id              BIGSERIAL PRIMARY KEY,
    tenant_id       BIGINT NOT NULL,
    org_id          BIGINT NOT NULL,
    schedule_id     BIGINT REFERENCES hss_service_schedules(id),
    plan_id         BIGINT NOT NULL,
    patient_id      BIGINT NOT NULL,
    staff_id        BIGINT,
    status          VARCHAR(32) NOT NULL DEFAULT 'ORDER_CREATED',
    service_date    DATE NOT NULL,
    scheduled_start TIME,
    scheduled_end   TIME,
    risk_level      VARCHAR(16),
    is_high_risk    BOOLEAN DEFAULT FALSE,
    version         INTEGER NOT NULL DEFAULT 0,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT,
    updated_by      BIGINT,
    deleted         SMALLINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_hss_wo_status ON hss_work_orders(status);
CREATE INDEX idx_hss_wo_staff ON hss_work_orders(staff_id);
CREATE INDEX idx_hss_wo_date ON hss_work_orders(service_date);
CREATE INDEX idx_hss_wo_patient ON hss_work_orders(patient_id);

CREATE TABLE hss_work_order_items (
    id              BIGSERIAL PRIMARY KEY,
    work_order_id   BIGINT NOT NULL REFERENCES hss_work_orders(id),
    plan_item_id    BIGINT NOT NULL,
    item_name       VARCHAR(128) NOT NULL,
    unit_price      DECIMAL(10,2) NOT NULL,
    required        BOOLEAN DEFAULT TRUE,      -- 是否必做
    status          VARCHAR(32) DEFAULT 'PENDING', -- COMPLETED/PARTIAL/NOT_COMPLETED/SKIPPED/USER_REFUSED
    evidence_required BOOLEAN DEFAULT FALSE,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);

-- 6. 执行域
CREATE TABLE hss_checkins (
    id              BIGSERIAL PRIMARY KEY,
    work_order_id   BIGINT NOT NULL REFERENCES hss_work_orders(id),
    checkin_type    VARCHAR(16) NOT NULL,       -- CHECKIN / CHECKOUT
    latitude        DECIMAL(10,7) NOT NULL,
    longitude       DECIMAL(10,7) NOT NULL,
    distance_meters INTEGER,                   -- 距目标地址距离
    photo_file_id   VARCHAR(64),
    patient_confirmed BOOLEAN,
    patient_signature_id VARCHAR(64),
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT
);

CREATE TABLE hss_execution_records (
    id              BIGSERIAL PRIMARY KEY,
    work_order_id   BIGINT NOT NULL,
    work_order_item_id BIGINT NOT NULL,
    status          VARCHAR(32) NOT NULL,       -- COMPLETED/PARTIAL/NOT_COMPLETED/SKIPPED/USER_REFUSED
    actual_start    TIMESTAMP,
    actual_end      TIMESTAMP,
    notes           TEXT,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT
);

CREATE TABLE hss_evidence_files (
    id              BIGSERIAL PRIMARY KEY,
    entity_type     VARCHAR(32) NOT NULL,       -- CHECKIN / EXECUTION / EXCEPTION / ACCEPTANCE
    entity_id       BIGINT NOT NULL,
    file_type       VARCHAR(16) NOT NULL,       -- PHOTO / VIDEO / AUDIO
    file_key        VARCHAR(256) NOT NULL,      -- 对象存储 key
    file_size       BIGINT,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT
);

-- 7. 异常域
CREATE TABLE hss_exceptions (
    id              BIGSERIAL PRIMARY KEY,
    work_order_id   BIGINT NOT NULL REFERENCES hss_work_orders(id),
    exception_type  VARCHAR(32) NOT NULL,       -- PATIENT_ABSENT / PATIENT_REFUSE / WRONG_ADDRESS / ...
    description     TEXT NOT NULL,
    evidence_file_ids TEXT,                     -- JSON 数组
    status          VARCHAR(32) NOT NULL DEFAULT 'REPORTED',
    handled_by      BIGINT,
    resolution      TEXT,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT
);

-- 8. 验收域
CREATE TABLE hss_acceptances (
    id              BIGSERIAL PRIMARY KEY,
    work_order_id   BIGINT NOT NULL REFERENCES hss_work_orders(id),
    status          VARCHAR(32) NOT NULL DEFAULT 'ACCEPTANCE_PENDING',
    result          VARCHAR(16),                -- ACCEPTED / REJECTED
    rating          SMALLINT,                   -- 1-5 星
    tags            TEXT,                       -- JSON 标签数组
    comment         TEXT,
    rejected_reason TEXT,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT
);

-- 9. 结算域
CREATE TABLE hss_settlements (
    id              BIGSERIAL PRIMARY KEY,
    tenant_id       BIGINT NOT NULL,
    org_id          BIGINT NOT NULL,
    patient_id      BIGINT NOT NULL,
    status          VARCHAR(32) NOT NULL DEFAULT 'SETTLEMENT_READY',
    period_start    DATE NOT NULL,
    period_end      DATE NOT NULL,
    total_amount    DECIMAL(12,2),
    insurance_deduction DECIMAL(12,2),
    self_pay_amount DECIMAL(12,2),
    paid_at         TIMESTAMP,
    payment_channel VARCHAR(32),
    payment_transaction_id VARCHAR(64),
    version         INTEGER NOT NULL DEFAULT 0,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMP NOT NULL DEFAULT NOW(),
    created_by      BIGINT,
    updated_by      BIGINT,
    deleted         SMALLINT NOT NULL DEFAULT 0
);

CREATE TABLE hss_settlement_items (
    id              BIGSERIAL PRIMARY KEY,
    settlement_id   BIGINT NOT NULL REFERENCES hss_settlements(id),
    work_order_id   BIGINT NOT NULL,
    execution_record_id BIGINT,
    item_name       VARCHAR(128),
    unit_price      DECIMAL(10,2),
    actual_amount   DECIMAL(10,2),
    deduction       DECIMAL(10,2),
    self_pay        DECIMAL(10,2),
    status          VARCHAR(32)
);

-- 10. 通知域
CREATE TABLE hss_notification_outbox (
    id              BIGSERIAL PRIMARY KEY,
    entity_type     VARCHAR(32) NOT NULL,
    entity_id       BIGINT NOT NULL,
    channel         VARCHAR(16) NOT NULL,       -- MQTT / WECHAT / SMS
    template_code   VARCHAR(64),
    params          JSONB,
    recipient_id    BIGINT,
    status          VARCHAR(16) NOT NULL DEFAULT 'CREATED',
    retry_count     INTEGER DEFAULT 0,
    max_retries     INTEGER DEFAULT 3,
    next_retry_at   TIMESTAMP,
    request_id      VARCHAR(64),
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_hss_nf_status ON hss_notification_outbox(status, next_retry_at);

CREATE TABLE hss_notification_receipts (
    id              BIGSERIAL PRIMARY KEY,
    outbox_id       BIGINT NOT NULL,
    status          VARCHAR(16) NOT NULL,       -- SENT / DELIVERED / READ / CONFIRMED / FAILED / EXPIRED
    sent_at         TIMESTAMP,
    delivered_at    TIMESTAMP,
    read_at         TIMESTAMP,
    error_message   TEXT,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);

-- 11. 审计域
CREATE TABLE hss_state_transitions (
    id              BIGSERIAL PRIMARY KEY,
    entity_type     VARCHAR(32) NOT NULL,       -- application / plan / work_order / settlement
    entity_id       BIGINT NOT NULL,
    from_status     VARCHAR(32),
    action          VARCHAR(32) NOT NULL,
    to_status       VARCHAR(32) NOT NULL,
    operator_id     BIGINT,
    operator_role   VARCHAR(32),
    reason          TEXT,
    request_id      VARCHAR(64),
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_hss_st_entity ON hss_state_transitions(entity_type, entity_id);
CREATE INDEX idx_hss_st_request ON hss_state_transitions(request_id);

CREATE TABLE hss_audit_logs (
    id              BIGSERIAL PRIMARY KEY,
    entity_type     VARCHAR(32),
    entity_id       BIGINT,
    action          VARCHAR(32) NOT NULL,
    operator_id     BIGINT,
    operator_name   VARCHAR(64),
    operator_role   VARCHAR(32),
    client_ip       VARCHAR(45),
    device_info     VARCHAR(256),
    detail          JSONB,
    is_sensitive    BOOLEAN DEFAULT FALSE,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_hss_al_entity ON hss_audit_logs(entity_type, entity_id);
CREATE INDEX idx_hss_al_operator ON hss_audit_logs(operator_id);
CREATE INDEX idx_hss_al_time ON hss_audit_logs(created_at);

-- 12. 合规域
CREATE TABLE hss_consent_records (
    id              BIGSERIAL PRIMARY KEY,
    patient_id      BIGINT NOT NULL,
    consent_type    VARCHAR(32) NOT NULL,       -- GPS / PHOTO / HEALTH / AUDIO_VIDEO
    consent_status  VARCHAR(16) NOT NULL,       -- GRANTED / REVOKED / EXPIRED
    granted_at      TIMESTAMP,
    revoked_at      TIMESTAMP,
    expires_at      TIMESTAMP,
    created_by      BIGINT,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE TABLE hss_data_access_logs (
    id              BIGSERIAL PRIMARY KEY,
    operator_id     BIGINT NOT NULL,
    data_type       VARCHAR(32) NOT NULL,       -- PERSONAL / HEALTH / LOCATION / FINANCIAL
    entity_type     VARCHAR(32),
    entity_id       BIGINT,
    access_action   VARCHAR(16) NOT NULL,       -- VIEW / EXPORT / DOWNLOAD
    client_ip       VARCHAR(45),
    reason          TEXT,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);

-- 唯一约束:幂等键
CREATE UNIQUE INDEX uk_hss_st_request ON hss_state_transitions(request_id, entity_type, entity_id);

8.2 执行顺序与窗口建议

阶段 脚本 内容 建议窗口
1 V1__baseline.sql 全部核心表创建 首次部署(停机窗口 10min
2 V2__seed_master_data.sql 主数据初始化(区域、服务项目、资质字典) 紧随 V1
3 V3__add_indexes.sql 性能索引补充 在线CREATE INDEX CONCURRENTLY
后续 V4+ 增量变更 按需,遵循 flyway 版本号

8.3 回滚策略

  • 每次迁移对应一个 U 版本回滚脚本(如 U1__baseline_rollback.sql
  • 回滚原则:非生产环境可直接 DROP生产环境采用 migrate down + data restore
  • 关键变更必须备份受影响数据:CREATE TABLE xxx_backup AS SELECT * FROM xxx WHERE ...
  • 禁止 DROP COLUMN 直接执行:先标记废弃 → 观察一个版本 → 再删除

9. 接口契约与兼容性

9.1 兼容性说明

方面 策略
账号/登录 兼容现有平台 JWT Token 格式
角色/权限 新增居家服务角色(受理员、评估员、方案制定员、调度员、服务人员、监管员、结算员),不影响现有角色
机构/用户 复用现有 org_id / user_id 体系
文件上传 复用现有对象存储接口,居家服务文件单独 folder
业务表 全新 hss_ 前缀,不影响现有业务表

9.2 版本管理

  • API 路径不加版本号,通过 Header Accept-Version 管理
  • 破坏性变更走新接口 + 旧接口保留一个版本后废弃

10. 自测与回归

10.1 单元测试范围

测试对象 覆盖内容
状态机 所有合法转换、非法转换拦截、重复提交幂等
校验服务 年龄校验、资格校验、重复申请校验
调度算法 硬约束过滤逻辑、软约束评分计算、Top5排序
结算计算 金额汇总、抵扣计算、部分完成折算

10.2 集成测试范围

测试场景 验证点
主链路 申请→评估→方案→工单→执行→验收→结算→归档 全流程
异常链路 退回、异议、拒签、改派、异常上报、拒绝验收、结算退回
通知链路 Outbox 写入→定时发送→回执记录
权限链路 角色隔离、数据范围过滤、字段脱敏
并发场景 同 request_id 重复提交、派单并发冲突

10.3 关键回归场景

  • 状态机规则变更后,所有上游调用方不受影响(规则集中管理)
  • 结算公式变更后,历史结算单金额不变(版本化快照)
  • 服务项目价格调整后,已签署方案不受影响(版本冻结)

11. 工程目录结构总览

hss-home-service/
├── pom.xml
├── src/
│   ├── main/
│   │   ├── java/com/meizhou/hss/
│   │   │   ├── HssApplication.java              # Spring Boot 启动类
│   │   │   ├── common/
│   │   │   │   ├── ApiResponse.java              # 统一响应
│   │   │   │   ├── BaseEntity.java               # 审计字段基类
│   │   │   │   ├── ErrorCode.java                # 错误码枚举
│   │   │   │   ├── BusinessException.java        # 业务异常
│   │   │   │   ├── Idempotent.java               # 幂等注解
│   │   │   │   ├── IdempotentAspect.java         # 幂等切面
│   │   │   │   ├── Auditable.java                # 审计注解
│   │   │   │   └── AuditAspect.java              # 审计切面
│   │   │   ├── config/
│   │   │   │   ├── SecurityConfig.java
│   │   │   │   ├── RedisConfig.java
│   │   │   │   ├── MqttConfig.java
│   │   │   │   ├── ObjectStorageConfig.java
│   │   │   │   ├── SchedulerConfig.java
│   │   │   │   ├── OpenApiConfig.java
│   │   │   │   └── MyBatisPlusConfig.java
│   │   │   ├── statemachine/
│   │   │   │   ├── StateMachine.java
│   │   │   │   ├── TransitionRule.java
│   │   │   │   ├── StateTransitionException.java
│   │   │   │   ├── ApplicationStateMachine.java
│   │   │   │   ├── PlanStateMachine.java
│   │   │   │   ├── WorkOrderStateMachine.java
│   │   │   │   └── SettlementStateMachine.java
│   │   │   └── module/
│   │   │       ├── application/
│   │   │       │   ├── controller/ApplicationController.java
│   │   │       │   ├── service/ApplicationService.java
│   │   │       │   ├── service/ApplicationValidationService.java
│   │   │       │   ├── repository/ServiceApplicationMapper.java
│   │   │       │   ├── entity/ServiceApplicationEntity.java
│   │   │       │   └── dto/{CreateRequest,SubmitRequest,Response,ListQuery}.java
│   │   │       ├── assessment/
│   │   │       │   ├── controller/AssessmentController.java
│   │   │       │   ├── service/AssessmentService.java
│   │   │       │   ├── repository/{AssessmentTaskMapper,AssessmentReportMapper}.java
│   │   │       │   ├── entity/{AssessmentTaskEntity,AssessmentReportEntity}.java
│   │   │       │   └── dto/{...}.java
│   │   │       ├── plan/
│   │   │       │   └── ... (同模式)
│   │   │       ├── schedule/
│   │   │       │   ├── controller/ScheduleController.java
│   │   │       │   ├── service/ScheduleService.java
│   │   │       │   ├── service/DispatchService.java
│   │   │       │   ├── algorithm/DispatchAlgorithm.java
│   │   │       │   ├── algorithm/HardConstraintFilter.java
│   │   │       │   ├── algorithm/SoftScoringRanker.java
│   │   │       │   └── ...
│   │   │       ├── workorder/
│   │   │       ├── execution/
│   │   │       ├── exception/
│   │   │       ├── supervision/
│   │   │       ├── acceptance/
│   │   │       ├── settlement/
│   │   │       ├── archive/
│   │   │       ├── notification/
│   │   │       │   ├── service/NotificationService.java
│   │   │       │   ├── sender/NotificationSender.java
│   │   │       │   ├── sender/MqttSender.java
│   │   │       │   ├── sender/WechatSender.java
│   │   │       │   └── sender/SmsSender.java
│   │   │       ├── audit/
│   │   │       ├── compliance/
│   │   │       ├── masterdata/
│   │   │       └── capacity/
│   │   └── resources/
│   │       ├── application.yml
│   │       ├── application-dev.yml
│   │       ├── application-test.yml
│   │       ├── application-prod.yml
│   │       └── db/migration/
│   │           ├── V1__baseline.sql
│   │           ├── V2__seed_master_data.sql
│   │           └── V3__add_indexes.sql
│   └── test/java/com/meizhou/hss/
│       ├── statemachine/
│       │   ├── ApplicationStateMachineTest.java
│       │   ├── PlanStateMachineTest.java
│       │   ├── WorkOrderStateMachineTest.java
│       │   └── SettlementStateMachineTest.java
│       ├── module/
│       │   ├── application/ApplicationControllerTest.java
│       │   ├── workorder/WorkOrderIntegrationTest.java
│       │   └── settlement/SettlementCalculationTest.java
│       └── algorithm/DispatchAlgorithmTest.java
└── delivery-miniapp/
    ├── pages/delivery/
    │   ├── login/
    │   ├── index/          # 工作台
    │   ├── orders/         # 工单列表
    │   ├── order-detail/   # 工单详情
    │   ├── accept/         # 接单确认
    │   ├── checkin/        # GPS签到
    │   ├── execute/        # 服务执行
    │   ├── exception/      # 异常上报
    │   ├── finish/         # 签退完成
    │   ├── offline-sync/   # 离线补传
    │   ├── messages/       # 通知消息
    │   └── profile/        # 我的资质
    └── ...

12. 实施优先级与分批计划(补齐版)

12.1 第一批MVP 可验收闭环)- 预计 4~6 周

第一批目标不是做全量美化和智能化,而是完成一条真实可验收的居家上门服务闭环:

申请 → 评估 → 方案 → 签署 → 服务计划 → 工单 → 派单 → delivery 接单 → 签到 → 项目执行 → 完成 → 验收 → 结算 → 归档

必须包含:

  1. 项目初始化:pom.xmlapplication.yml、启动类、环境配置。
  2. 公共模块:ApiResponseBaseEntity、统一异常、错误码、分页、租户上下文。
  3. 数据库基线Flyway migration包含 P0/P1 核心表。
  4. 状态机:申请、方案、工单、结算四层状态机。
  5. 状态动作编排:ActionHandler,完成状态流转 + 副作用写入。
  6. 幂等模块:hss_idempotency_records + Idempotency-Key 拦截器。
  7. Outbox 模块:写入、并发抢占、重试、死信、回执。
  8. 审计模块:状态流转、敏感数据访问、高风险操作审计。
  9. 申请域:创建、提交、受理通过、退回、取消。
  10. 评估域:派发、签到、提交报告、异议。
  11. 方案域:创建、编辑、提交签署、签署、拒签、版本管理。
  12. 计划域:方案生效后生成服务计划。
  13. 工单域:工单创建、派单、接单、拒单、改派。
  14. 执行域GPS 签到、项目级执行记录、证据元数据、完成。
  15. 异常域:异常上报、异常处理动作、紧急事件基础流程。
  16. 验收域:验收确认、拒绝验收、评价。
  17. 结算域:结算单、结算明细、审核、支付确认、归档。
  18. 支付退款域:支付流水、重复回调幂等、退款/冲正基础表。
  19. 定时任务Outbox 重试、派单超时扫描、方案待签提醒、验收超时扫描。
  20. delivery 最小闭环页面:登录、工作台、今日工单、详情、接单、签到、执行、异常、完成、证据上传、消息。
  21. OpenAPI 契约:覆盖 MVP 全部接口。
  22. E2E 测试:完成至少 1 条从申请到归档的完整链路。

12.2 第二批(增强能力)- 预计 3~4 周

  1. 调度算法:硬约束过滤 + 软约束评分 + Top5 推荐解释。
  2. 监管域:抽查计划、违规记录、整改跟踪。
  3. 合规域:授权同意、敏感数据访问审计、脱敏策略完善。
  4. 主数据域:机构、人员、资质、服务项目、区域、价格、规则版本。
  5. 文件证据增强:断点/失败补传、文件 hash、签名 URL、下载审计。
  6. 定时任务增强:未来 1~7 天工单生成、次日排班预计算、批量结算。
  7. delivery 离线能力:本地缓存、失败补传、重复提交防护。
  8. 管理端调度台:改派、撤单、异常处理、超时预警。
  9. 权限矩阵落地:接口级权限、字段级脱敏、数据范围过滤。
  10. Testcontainers 集成测试PostgreSQL、Redis、MQTT/Mock、对象存储。

12.3 第三批(智能化与运营)- 后续迭代

  1. 运力域:服务网格、容量预测、网格容量看板。
  2. ETA 预测:到达时间、完成时间、风险缓冲。
  3. 调度优化局部搜索、插入成本、OR-Tools 批量预排。
  4. 数据看板:质量分析、异常热力图、服务连续性、人员负载。
  5. 人员绩效结算:服务质量、完成率、投诉率、违规率、评分。
  6. 智能助手delivery 端风险提醒、证据缺失提醒、异常处理建议。

13. 开始实现 Prompt补齐版

13.1 第一阶段开工 Prompt

你现在作为资深 Spring Boot 后端工程师,在全新仓库中实现“居家上门服务系统”的 MVP 第一批。

必须遵守:
1. 技术栈Spring Boot 3.x + Java 17 + PostgreSQL + MyBatis-Plus/Spring Data JDBC + Flyway + Redis + MQTT + 对象存储。
2. 架构:模块化单体,不拆微服务,但按 domain/module 分包。
3. 表规范:所有业务表使用 hss_ 前缀,必须包含 tenant_id、org_id、status、created_by、updated_by、created_at、updated_at、deleted_at、version。
4. 状态机:申请、方案、工单、结算四层状态机;前端只传 action不传目标状态。
5. 状态动作状态机只判断合法性ActionHandler 负责编排副作用例如写业务表、状态流转、Outbox、审计。
6. 幂等:所有写接口支持 Idempotency-Key并落库 hss_idempotency_records。
7. 通知:所有通知必须先写 hss_notification_outbox异步发送Outbox 必须支持并发锁、重试、dead-letter。
8. 结算:结算金额由后端基于方案快照和执行记录计算,禁止使用前端传入金额作为最终金额。
9. 文件证据文件进入对象存储数据库只保存元数据、hash、storage_key、访问审计。
10. delivery 端MVP 必须包含登录、今日工单、详情、接单、签到、执行、异常、完成、证据上传、消息。
11. 测试必须包含状态机单测、金额计算单测、幂等测试、Outbox 失败重试测试、支付重复回调测试、定时任务重复执行测试。
12. 输出Flyway DDL、Java 代码、OpenAPI 契约、状态机文档、数据字典、测试用例。

第一阶段只做 MVP 可验收闭环,不做复杂 ETA、OR-Tools、智能推荐、完整数据看板。
先生成工程目录、pom.xml、application.yml、Flyway V1~V10 migration、BaseEntity、ApiResponse、错误码、幂等拦截器、状态机骨架、Outbox 骨架,然后再实现申请域、评估域、方案域、计划域、工单域、执行域、验收域、结算域。

14. 生产可交付补强清单

14.1 P0 必须补齐项

编号 补齐项 必须完成的内容 不完成的风险
P0-01 幂等落库 新增 hss_idempotency_records,所有写接口接入 重复提交、重复支付、重复生成工单
P0-02 定时任务日志 新增 hss_job_execution_logs 定时任务失败不可追溯、不可重跑
P0-03 Outbox 并发安全 locked_bylocked_untilnext_retry_atdead-letter 多实例重复发送、通知堆积
P0-04 delivery MVP 登录、今日工单、详情、接单、签到、执行、异常、完成、证据上传 无法验证真实上门履约
P0-05 方案签署事务 签署记录、方案生效、服务计划生成、状态流转、Outbox 同事务 方案已生效但没有计划
P0-06 证据元数据 hss_evidence_files 完整字段、对象存储、hash、签名访问 服务执行证据链不可信
P0-07 支付幂等 支付流水号 + 结算单号幂等 重复支付回调导致账务错误
P0-08 状态动作编排 StateMachine + ActionHandler 双层结构 service 逻辑膨胀,状态副作用失控

14.2 P1 必须补齐项

编号 补齐项 必须完成的内容
P1-01 异议闭环 hss_objections,评估异议、方案异议、复核记录
P1-02 异常动作 hss_exception_actions,每一次处理动作留痕
P1-03 监管整改 hss_spot_checkshss_violationshss_corrections
P1-04 投诉反馈 hss_complaints,与验收拒绝区分
P1-05 支付退款 hss_paymentshss_refunds、冲正记录
P1-06 归档台账 hss_ledgershss_archive_files
P1-07 主数据 服务项目、资质、区域、价格、机构、人员
P1-08 OpenAPI 完整契约 消费者端、管理端、delivery 端、定时任务管理接口

15. 完整 DDL 补齐范围

15.1 必须进入 baseline 的核心表

第一版 Flyway 不建议只建少量表再频繁补核心表。MVP 可以不实现全部业务逻辑,但核心表结构应尽量一次性建立,避免后续状态和数据迁移困难。

数据域 表名
申请 hss_service_applications
画像 hss_patient_profiles
评估 hss_assessment_taskshss_assessment_reports
异议 hss_objections
方案 hss_service_planshss_service_plan_itemshss_plan_versions
计划 hss_service_schedules
工单 hss_work_ordershss_work_order_items
执行 hss_checkinshss_execution_recordshss_evidence_files
异常 hss_exceptionshss_exception_actions
监管 hss_spot_checkshss_violationshss_corrections
验收 hss_acceptanceshss_complaints
结算 hss_settlementshss_settlement_items
支付 hss_paymentshss_refunds
归档 hss_ledgershss_archive_files
通知 hss_notification_outboxhss_notification_receipts
幂等 hss_idempotency_records
任务 hss_job_execution_logs
审计 hss_state_transitionshss_audit_logshss_data_access_logs
合规 hss_consent_records
主数据 hss_md_organizationshss_md_staffhss_md_staff_qualificationshss_md_service_itemshss_md_price_ruleshss_md_regions
运力 hss_service_gridshss_grid_capacity_dailyhss_staff_skill_capacity

15.2 新增关键表字段建议

hss_idempotency_records

CREATE TABLE hss_idempotency_records (
  id BIGSERIAL PRIMARY KEY,
  tenant_id BIGINT NOT NULL,
  idempotency_key VARCHAR(128) NOT NULL,
  business_key VARCHAR(256) NOT NULL,
  request_hash VARCHAR(128) NOT NULL,
  response_code VARCHAR(64),
  response_body TEXT,
  status VARCHAR(32) NOT NULL,
  locked_until TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (tenant_id, idempotency_key, business_key)
);

hss_notification_outbox

CREATE TABLE hss_notification_outbox (
  id BIGSERIAL PRIMARY KEY,
  tenant_id BIGINT NOT NULL,
  business_type VARCHAR(64) NOT NULL,
  business_id BIGINT NOT NULL,
  event_type VARCHAR(64) NOT NULL,
  receiver_id BIGINT NOT NULL,
  channel VARCHAR(32) NOT NULL,
  payload JSONB NOT NULL,
  status VARCHAR(32) NOT NULL,
  retry_count INT NOT NULL DEFAULT 0,
  max_retry_count INT NOT NULL DEFAULT 5,
  next_retry_at TIMESTAMPTZ,
  locked_by VARCHAR(128),
  locked_until TIMESTAMPTZ,
  sent_at TIMESTAMPTZ,
  last_error TEXT,
  dedupe_key VARCHAR(256) NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (tenant_id, dedupe_key)
);

hss_job_execution_logs

CREATE TABLE hss_job_execution_logs (
  id BIGSERIAL PRIMARY KEY,
  tenant_id BIGINT NOT NULL,
  job_name VARCHAR(128) NOT NULL,
  biz_date DATE NOT NULL,
  shard_key VARCHAR(128) NOT NULL DEFAULT 'default',
  status VARCHAR(32) NOT NULL,
  started_at TIMESTAMPTZ NOT NULL,
  finished_at TIMESTAMPTZ,
  success_count INT NOT NULL DEFAULT 0,
  failure_count INT NOT NULL DEFAULT 0,
  error_message TEXT,
  idempotency_key VARCHAR(256) NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (tenant_id, job_name, biz_date, shard_key)
);

16. 状态机与动作编排补齐设计

16.1 为什么不能只有 transition 方法

状态机不能只做:

from_status + action = to_status

因为每个动作都有副作用。例如“方案签署”必须同时完成:

  1. 校验方案版本。
  2. 校验签署人。
  3. 写签署记录。
  4. 冻结方案快照。
  5. 生成服务计划。
  6. 写状态流转。
  7. 写 Outbox。
  8. 写审计日志。

16.2 推荐双层结构

StateMachine判断动作是否合法
ActionHandler执行业务副作用

目录建议:

statemachine/
  StateMachine.java
  TransitionRule.java
  TransitionContext.java
  TransitionResult.java
  ApplicationStateMachine.java
  PlanStateMachine.java
  WorkOrderStateMachine.java
  SettlementStateMachine.java

action/
  ApplicationSubmitHandler.java
  ApplicationAcceptHandler.java
  AssessmentSubmitHandler.java
  PlanSubmitSignHandler.java
  PlanSignHandler.java
  WorkOrderAssignHandler.java
  WorkOrderAcceptHandler.java
  WorkOrderCheckInHandler.java
  WorkOrderFinishHandler.java
  WorkOrderExceptionHandler.java
  AcceptanceConfirmHandler.java
  SettlementApproveHandler.java
  PaymentCallbackHandler.java

16.3 ActionHandler 标准流程

1. 加载业务对象
2. 校验租户、机构、角色、数据范围
3. 校验 Idempotency-Key
4. 调用 StateMachine 校验动作合法性
5. 执行业务副作用
6. 更新业务状态
7. 写 hss_state_transitions
8. 写 hss_audit_logs
9. 写 hss_notification_outbox
10. 提交事务
11. 返回动作结果

17. Outbox 并发安全与补偿机制

17.1 Outbox 发送状态

状态 含义
CREATED 已创建,待发送
LOCKED 已被某个实例抢占
SENT 已发送成功
FAILED 本次发送失败,等待重试
DEAD 超过最大重试次数,进入死信

17.2 多实例抢占策略

PostgreSQL 推荐使用 FOR UPDATE SKIP LOCKED

SELECT *
FROM hss_notification_outbox
WHERE status IN ('CREATED', 'FAILED')
  AND (next_retry_at IS NULL OR next_retry_at <= now())
ORDER BY created_at
LIMIT 100
FOR UPDATE SKIP LOCKED;

发送任务拿到记录后更新为 LOCKED,设置 locked_bylocked_until。发送成功后更新为 SENT,失败则增加 retry_count 并设置 next_retry_at。超过最大重试次数进入 DEAD

17.3 失败补偿

  1. FAILED 可自动重试。
  2. DEAD 必须进入运营或技术告警。
  3. 支持按业务 ID 手动重发。
  4. 支持按时间区间批量重发。
  5. 通知通道失败不能回滚业务主状态。
  6. 消费者端和 delivery 端必须能通过主动查询拿到真实业务状态。

18. delivery 端 MVP 最小闭环

18.1 MVP 页面范围

页面 是否 MVP 必须 说明
登录页 校验服务人员角色、机构、状态
工作台 今日任务、待接单、待签到、服务中、异常
今日工单 查询本人任务
工单详情 地址、对象脱敏信息、服务项目、风险提示
接单/拒单 触发工单状态机
签到 GPS、拍照、对象确认
执行 项目级执行记录
异常 对象不在家、拒绝服务、身体异常、地址错误等
完成 提交服务总结、证据校验
证据上传 文件上传、hash、元数据
消息页 派单、改派、异常处理、验收反馈
离线补传 第二批 MVP 可先做失败重试,不做完整离线队列
智能助手 第三批 风险提醒、路径建议、语音输入

18.2 delivery 聚合接口

GET  /api/hss/delivery/workbench
GET  /api/hss/delivery/work-orders/today
GET  /api/hss/delivery/work-orders/{id}/detail
POST /api/hss/delivery/work-orders/{id}/accept
POST /api/hss/delivery/work-orders/{id}/reject
POST /api/hss/delivery/work-orders/{id}/check-in
POST /api/hss/delivery/work-orders/{id}/start-service
POST /api/hss/delivery/work-orders/{id}/execution-records
POST /api/hss/delivery/work-orders/{id}/finish
POST /api/hss/delivery/work-orders/{id}/exception
POST /api/hss/delivery/evidence/upload
GET  /api/hss/delivery/messages
POST /api/hss/delivery/messages/{id}/read

19. 完整 OpenAPI 接口补齐范围

19.1 消费者端接口

POST /api/hss/applications
POST /api/hss/applications/{id}/submit
POST /api/hss/applications/{id}/cancel
GET  /api/hss/applications/{id}
GET  /api/hss/service-plans/{id}/for-sign
POST /api/hss/service-plans/{id}/sign
POST /api/hss/service-plans/{id}/reject
GET  /api/hss/work-orders/{id}/acceptance
POST /api/hss/work-orders/{id}/acceptance/confirm
POST /api/hss/work-orders/{id}/acceptance/reject
POST /api/hss/work-orders/{id}/rating
GET  /api/hss/settlements/{id}
POST /api/hss/settlements/{id}/pay

19.2 管理端接口

GET  /api/hss/admin/applications
POST /api/hss/admin/applications/{id}/accept
POST /api/hss/admin/applications/{id}/return
POST /api/hss/admin/assessment-tasks/{id}/assign
POST /api/hss/admin/service-plans
PUT  /api/hss/admin/service-plans/{id}
POST /api/hss/admin/service-plans/{id}/submit-sign
POST /api/hss/admin/service-plans/{id}/generate-schedule
POST /api/hss/admin/work-orders/{id}/assign
POST /api/hss/admin/work-orders/{id}/reassign
POST /api/hss/admin/work-orders/{id}/cancel
POST /api/hss/admin/exceptions/{id}/handle
POST /api/hss/admin/settlements/generate
POST /api/hss/admin/settlements/{id}/approve
POST /api/hss/admin/settlements/{id}/reject
GET  /api/hss/admin/audit-logs

19.3 文件与证据接口

POST /api/hss/files/presign-upload
POST /api/hss/files/commit
GET  /api/hss/files/{id}/signed-url
GET  /api/hss/evidence-files/by-work-order/{workOrderId}

19.4 主数据接口

GET  /api/hss/master/service-items
GET  /api/hss/master/price-rules
GET  /api/hss/master/regions
GET  /api/hss/master/staff
GET  /api/hss/master/staff/{id}/qualifications

20. 定时任务补齐设计

20.1 必须实现的 MVP 任务

任务 频率 MVP 是否必须
Outbox 重试 每 1 分钟
派单超时扫描 每 5 分钟
方案待签提醒 每 30 分钟
服务开始前提醒 每 10 分钟
验收超时扫描 每小时
未来工单生成 每晚 00:30 第二批也可,但表和接口先预留
次日排班预计算 每晚 01:00 第二批
批量结算生成 每日/每月 第二批
审计日志归档 每月 第二批

20.2 任务执行规则

  1. 所有任务写 hss_job_execution_logs
  2. 所有任务按 job_name + biz_date + shard_key 幂等。
  3. 所有任务支持 dry-run。
  4. 所有任务支持手动重跑。
  5. 所有任务不得绕过状态机直接改状态。
  6. 多实例部署必须使用分布式锁或数据库唯一键防重复。

21. 测试与验收补齐

21.1 新增必测用例

类型 用例
幂等 同一 Idempotency-Key 重复提交返回同一结果
幂等冲突 同一 Idempotency-Key 不同 body 返回冲突
并发派单 两个调度员同时派同一工单,只能成功一次
并发接单 服务人员重复点击接单,只生成一次接单记录
并发完成 重复完成提交不生成重复执行记录
Outbox 失败 MQTT 失败后 Outbox 进入 FAILED 并可重试
Outbox 死信 超过最大次数进入 DEAD
支付回调 同一支付流水重复回调只入账一次
事务回滚 服务计划生成失败时方案签署整体回滚
文件补传 文件上传成功但业务提交失败,可重新绑定
权限 服务人员不能查看非本人工单
脱敏 非授权角色看不到完整手机号、地址、健康信息
任务重跑 同一天重复生成工单不产生重复数据
弱网 delivery 端重复点击、网络失败、恢复补传

21.2 MVP 验收门槛

  1. 状态机核心分支单测覆盖率 ≥ 90%。
  2. 结算金额计算单测覆盖率 ≥ 90%。
  3. 所有写接口必须有幂等测试。
  4. 所有状态动作必须有非法状态测试。
  5. delivery 端完成 5 条 E2E接单、签到、执行、异常、完成。
  6. Outbox 完成失败重试和死信测试。
  7. 支付回调完成重复回调测试。
  8. 定时任务完成重复执行测试。
  9. 权限和脱敏至少覆盖服务人员、调度员、结算员、监管员四类角色。
  10. OpenAPI 与实际接口保持一致。

22. 灰度发布与回滚补齐

22.1 发布策略

能力 发布方式
状态机 测试环境全量验证后上线,不做灰度状态
调度算法 shadow 模式 → 人工确认 → 小范围自动
自动验收 默认关闭,试点机构开启
批量结算 dry-run → 人工审核 → 自动生成
delivery 新页面 按机构/角色灰度
定时任务 小范围 biz_date dry-run 后开启
Outbox 先发送测试通道,再切真实通道

22.2 回滚原则

  1. 数据库以 roll-forward 为主,不依赖直接 down migration。
  2. 已上线的 migration 不修改,新增 migration 修正。
  3. 删除字段必须两阶段:先停用,后删除。
  4. 新状态上线前必须确认旧代码能兼容或不会读取。
  5. 功能必须有 feature flag。
  6. 回滚后不能产生孤儿状态。
  7. 任务必须可暂停、可恢复、可重跑。

23. 最终开工检查清单

开始实现前,必须确认以下事项:

检查项 是否必须
已确认 Spring Boot / Java 17 / PostgreSQL / Redis / MQTT / 对象存储
已确认 hss_ 表前缀、统一审计字段、软删除、乐观锁
已确认方案、计划、工单分离
已确认工单项目级执行记录
已确认所有写接口 Idempotency-Key
已确认新增 hss_idempotency_records
已确认新增 hss_job_execution_logs
已确认 Outbox 支持锁、重试、死信
已确认 delivery MVP 进入第一批
已确认支付、退款独立表
已确认异常、监管、投诉独立闭环
已确认 OpenAPI 全契约先行
已确认 Testcontainers/真实依赖集成测试
已确认灰度开关和 roll-forward 回滚策略

24. 最终结论

这份补齐版已经可以作为正式开工文档使用。实现时不要再扩大需求范围,第一阶段只围绕“真实可验收闭环”推进:

后端状态机可信
数据库链路完整
通知可靠可补偿
delivery 可真实履约
结算可追溯
异常可兜底
权限与审计可验收
测试能证明系统可靠

第一阶段完成后,系统应能真实跑通:

家属提交申请
→ 受理员受理
→ 评估员评估
→ 管理端生成方案
→ 家属签署方案
→ 系统生成服务计划和工单
→ 调度员派单
→ delivery 服务人员接单
→ GPS 签到
→ 项目级执行
→ 上传证据
→ 完成服务
→ 家属验收
→ 系统生成结算
→ 支付确认
→ 归档

只要严格按本补齐版执行,就可以开始实现。