Files
railwaysystem/docs/development/dms-r3/03_domain_mapping.md
T

11 KiB
Raw Blame History

03 RailwaySystem 与 DMS 领域模型映射体系 (Domain Mapping)

核心原则:RailwaySystem 是住宿业务事实的唯一真源 (Source of Truth)。 DMS 平台仅作为外部门禁与物联网设备的执行端与监控端。 严禁:以 DMS 房间状态 (status) 直接替代 RailwaySystem 住宿占用与床位台账。


1. 核心实体对应关系总览 (Mermaid 架构图)

classDiagram
    direction TB

    class RailwayTrainingPlan {
        +String planId "内部培训班计划ID"
        +String planName
        +Date trainStart
        +Date trainEnd
    }

    class RailwayEnrollment {
        +Long enrollmentId "参训学员档案ID"
        +String planId
        +String studentId
        +Integer reportStatus
    }

    class RailwayAccommodation {
        +Long accommodationId "住宿安排事实ID (Source of Truth)"
        +Long enrollmentId
        +String dormId
        +String bedNo
        +Integer accommodationStatus "0预分配, 1已入住, 2已退宿"
    }

    class RailwayDormitoryInfo {
        +String dormId "本地宿舍UUID"
        +String dormBuilding "楼栋"
        +String dormFloor "楼层"
        +String dormRoom "房号"
        +Integer capacity "床位容量"
    }

    class ExternalResourceMapping {
        +Long mappingId
        +String localDormId "关联本地宿舍"
        +Long dmsProjectId "DMS租户/物业站点ID"
        +Long dmsPlaceId "DMS房间ID"
        +String dmsBuilding
        +String dmsFloor
        +String dmsRoom
        +Integer mappingStatus "1已绑定, 0待校验"
    }

    class DmsPlaceRoom {
        <<DMS Remote>>
        +Long id "DMS placeId"
        +Long projectId "DMS租户ID (≠ planId)"
        +String building
        +String floor
        +String room
    }

    class DmsDoorLock {
        <<DMS Remote>>
        +Long lockId "DMS锁ID"
        +String hardwareId "锁硬件SN (如 5C9F539A)"
        +Long placeId
        +Integer battery
        +Integer signal
    }

    class DoorAuthorization {
        +Long authId "本地授权凭证主记录"
        +Long accommodationId
        +Long dmsLockId
        +String dmsHardwareId
        +Long dmsKeyId "DMS返回的钥匙ID"
        +String credentialType "PASSWORD / CARD"
        +Timestamp validStart
        +Timestamp validUntil
        +Integer authStatus "PENDING / ACTIVE / REVOKED"
    }

    class ExternalOperationRecord {
        +Long operationLocalId
        +Long authId
        +String dmsOperationId "DMS异步操作流水ID"
        +Integer requestType "1下发密码, 3删除密码等"
        +String operationStatus "undone / success / failed / timeout"
        +Integer pollCount
        +Timestamp nextPollTime
    }

    RailwayTrainingPlan "1" --> "0..*" RailwayEnrollment : 包含
    RailwayEnrollment "1" --> "1" RailwayAccommodation : 产生住宿安排
    RailwayAccommodation "0..*" --> "1" RailwayDormitoryInfo : 分配房间
    RailwayDormitoryInfo "1" --> "0..1" ExternalResourceMapping : 稳定映射
    ExternalResourceMapping "1" ..> "1" DmsPlaceRoom : 对应DMS物理房间
    DmsPlaceRoom "1" ..> "0..*" DmsDoorLock : 挂载智能门锁 (支持一房多锁)
    RailwayAccommodation "1" --> "0..*" DoorAuthorization : 派生门锁授权
    DoorAuthorization "1" --> "0..*" ExternalOperationRecord : 追踪异步执行

2. 关键实体边界与重大概念澄清

2.1 铁律:DMS projectId ≠ RailwaySystem Training Plan ID

  • DMS projectId(示例中为 319402846、3837087560):代表 DMS 物联网平台的物业项目/租户/公寓站点 ID。属于系统级或物理站点级的静态上下文配置,由设备供应商分配。
  • RailwaySystem plan_id(如 PLAN20260901):代表铁路局/段内的具体教学培训开班批次。生命周期通常为几天到几周。
  • 红线:严禁将 DMS projectId 错写成或动态传为学员开班 planId!在配置文件中应统一作为 dms.project-id 进行站点级静态受控配置。

2.2 铁律:本地住宿事实是唯一真源 (Local Source of Truth)

  • DMS 的 room.status(0:空置, 1:已入住, 2:脏房等)仅为其平台或第三方酒店系统的简单标记,绝对不能用于覆盖或推断 RailwaySystem 的床位与入住状态。
  • 只有 RailwaySystem 自身的 train_accommodation 与 train_enrollment 能决定学员是否在住、床位是否已满、是否已报到。
  • DMS 门锁授权状态仅是硬件执行层面的技术属性(开门凭据是否已在锁具上成功生效)。

3. 房间与门锁映射策略深度比选 (Mapping Proposals)

3.1 房间映射 (Local Dormitory ↔ DMS Place)

DMS 提供了两种查询房间的途径:

  • 模糊查询列表:POST /rest/place/room/list
  • 精确查询:POST /rest/place/room/get(入参:building, floor, room)
方案 实现方式 优缺点分析 结论
方案 1:直接在 train_dormitory_info 加列 增加 dms_place_id, dms_project_id, dms_sync_time 优点:查询直观,单表读取。
缺点:污染本地物理宿舍模型;若未来接入其他门禁厂商(如海康、大华),列定义难以复用。
可作为一期过渡备选
方案 2:独立 train_external_resource_mapping 映射表 建立独立映射表:local_resource_type ('DORMITORY'), local_id, vendor ('DMS'), external_id (placeId), metadata_json 优点:模型高度解耦;本地宿舍资源生命周期不受外部影响;天然支持多厂商与资源解绑/重绑。
缺点:需要多做一次关联查询。
推荐采纳

映射规则明确:

  • 严禁每次下发授权时现场调用 /rest/place/room/get 进行文本字符串模糊匹配。网络抖动或楼栋名称微小差异(例如 "1号楼" vs "楼栋1")会导致授权链路阻断。
  • 必须在管理端提供“房源映射绑定/同步”功能,预先在数据库中持久化 localDormId ↔ dmsPlaceId 的权威主键映射。

3.2 门锁映射:支持“一房多锁”模型 (One Room to Multi-Locks)

DMS 接口 POST /rest/doorlock/list(入参 placeId)返回的是一个门锁列表:rows: [...]。 这证实了物理现实:一个公寓房间可能没有门锁(0把)、有一把门锁(1把)、或者有多个门锁(例如外防盗门锁 + 内卧室锁,多把锁)。

  • 错误做法:在 train_dormitory_info 中仅保留单一的 lock_device_sn 字符串,假设一房仅有一锁。
  • 推荐设计:
    • 系统必须能够处理一个 placeId 对应 0..N 把门锁的情况。
    • 当为学员下发该房间的开门权限时,集成适配器应查询该房间绑定的所有有效门锁,并为每把锁分别申请/下发开门凭据,生成对应的 DoorAuthorization 记录。

4. 详细字段级映射字典 (Field-Level Mapping Dictionary)

4.1 宿舍/房间信息映射

RailwaySystem 本地字段 DMS 对应字段 类型转换 / 映射规则 说明
train_dormitory_info.dorm_id mapping.local_dorm_id VARCHAR(32) (UUID) 本地主键
- dms.place.id / placeId BIGINT DMS 房间全局唯一主键
train_dormitory_info.dorm_building dms.place.building 字符串精确比对/绑定 宿舍楼栋名
train_dormitory_info.dorm_floor dms.place.floor 字符串精确比对/绑定 所在楼层
train_dormitory_info.dorm_room dms.place.room 字符串精确比对/绑定 房间号
- dms.place.projectId BIGINT 系统级受控站点配置

4.2 门锁设备信息映射

RailwaySystem 本地概念 DMS 对应字段 类型 / 格式 说明
mapping.external_lock_id doorlock.id BIGINT DMS 门锁管理 ID
train_dormitory_info.lock_device_sn doorlock.hardwareId VARCHAR(64) (如 5C9F539A) 门锁硬件 SN / 通信 ID
device_battery doorlock.battery INT (0~100, 255为未知) 门锁电量
device_signal doorlock.signal INT (-100~0, -128为未知) 信号强度 (RSSI)

4.3 门禁授权与钥匙下发映射 (Online Password 场景)

RailwaySystem 本地字段 DMS 对应入参 / 字段 映射规则与约束
train_accommodation.accommodation_id - 本地业务事实归属
target_lock_id create.lockId 目标门锁的 DMS ID
auth_start (配合提早 Buffer) create.validStart 毫秒级时间戳 (Long)
auth_end (配合延后 Buffer) create.validUntil 毫秒级时间戳 (Long)
student_name create.holder 学员姓名 (可选,建议填写真实姓名)
- create.canOpenAntilock 固定设为 false (不可开反锁,保障私密安全)
phone_country create.phoneCountry 默认 +86
student_phonenumber create.phoneNumber 学员手机号
door_password (一次性生成或安全受控) create.password 系统可生成4~8位纯数字密码,Pilot建议采用6位限时密码
credential_sub_type create.subType 固定为 4 (限时密码)
external_key_id 返回的 data.id DMS 钥匙全局 ID (退宿撤权时作为删除入参)
dms_operation_id 返回的 data.operationId DMS 异步下发任务 ID (用于10秒后状态轮询)

5. Wave 1 Implementation Result (Wave 1 implemented)

  • 阶段状态:Wave 1 implemented(外部资源映射模型与外部操作流水持久化模型已交付并验证)。
  • 资源映射基数与引用模型 (RESOURCE_MAPPING_REFERENCE_MODEL = DORM_ID_FK):
    • 本地采用 dorm_id 外键强关联 train_dormitory_info,确保一期完整性与零类型歧义。
    • 房间映射基数:ROOM_MAPPING_CARDINALITY = Dormitory 1:0..1 Active Room (Dormitory 1:N History),同一宿舍在同一 Vendor 下最多只能有 1 个处于 ACTIVE 状态的房间映射(通过局部唯一索引 uq_ext_res_map_active_room 严格保障)。
    • 门锁映射基数:LOCK_MAPPING_CARDINALITY = Dormitory 1:0..N DoorLocks,支持一房多锁(防盗门、内门、套间门),is_primary 区分主从门锁。
    • 外部资源唯一性:EXTERNAL_RESOURCE_ACTIVE_UNIQUENESS = Vendor + External Resource ID + Active Unique,同一外部资源在同一厂商下严禁跨房间重复 ACTIVE 绑定(通过局部唯一索引 uq_ext_res_map_active_ext_res 保障)。
  • 操作流水基数与引用模型 (OPERATION_REFERENCE_MODEL = DOOR_AUTH_ID_FK):
    • 本地采用 door_auth_id 外键强关联 train_dorm_auth,业务类型默认为 DOOR_AUTH。
    • 操作流水基数:DOOR_AUTH_OPERATION_CARDINALITY = DoorAuthorization 1:N ExternalOperation,每次具体下发、重试、撤销均保留独立流水行,禁止直接覆写。
    • 状态机与幂等:OPERATION_STATUS_MODEL 包含从 CREATED 到 SUCCESS/FAILED/TIMEOUT/RETRY_WAIT 的合法单向流转(REVOKED 属于 DoorAuthorization 业务状态,单次注销流水为 operation_type=REVOKE 达成 SUCCESS),终态不可逆;idempotency_key 唯一索引全局防重。
  • 敏感数据治理:不存 raw JSON、密码明文、卡号明文、Token、Secret,敏感字段数为 0。
  • 数据库迁移安全:008_external_resource_operation.sql 已通过静态契约测试与幂等验证,生产库保持零变更。