Files
patbond-doc/docs/development/iterations/iteration-2/openapi-pets-draft.yaml
T
lixi 222990e587
CI / docs-build (push) Successful in 1m19s
docs: M2 第二波收口——报告 13~21 与契约草案入档挂导航
- 13~18 后端纵切六单报告(T2-03~08,测试 95→182)
- 14 + openapi-pets-draft.yaml 契约起草档案
- 19 契约冻结报告(v1.2.0,22 项草案修正对照)
- 20 契约一致性测试(快照机制 + 1 漂移修复)
- 21 第二波收口总表(定型语义汇总,第三波接入依据)
- mkdocs build --strict 通过

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-08 10:40:27 +08:00

1717 lines
48 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.0.3
info:
title: Patbond API — Pets Domain (M2 Draft)
version: 1.2.0-draft
description: |
M2 宠物健康档案域契约草案(起草态,待 T2-03 权限/错误语义与 T2-08 聚合字段定型后冻结)。
本草案扩展既有 1.1.0 契约(6 端点:auth 4 + me 1 + events 1),增加 pets 域全部端点。
**未冻结,字段可能变更**;冻结后任何变更须显著上报、两端同步。
## Pets 域端点概览(本草案范围)
- 宠物 CRUDGET/POST /api/v1/pets、GET/PATCH /api/v1/pets/{petId}
- 品种目录:GET /api/v1/breeds(按 species 过滤)
- 体重记录:GET/POST /api/v1/pets/{petId}/weightscursor 分页)
- 疫苗目录:GET /api/v1/vaccine-catalog(按 species 过滤)
- 疫苗记录:GET/POST /api/v1/pets/{petId}/vaccinations、PATCH /api/v1/vaccinations/{vaccinationId}
- 健康事件:GET/POST /api/v1/pets/{petId}/health-events、PATCH /api/v1/health-events/{eventId}
- 照护提醒:GET/POST /api/v1/pets/{petId}/care-reminders、PATCH /api/v1/care-reminders/{reminderId}
- 档案聚合:GET /api/v1/pets/{petId}/summary(最新体重、疫苗进度、下次接种、当月花费)
## 通用约定(继承既有契约)
- 公开接口统一前缀 `/api/v1`JSON 字段一律 `camelCase`;资源 ID 为 UUID 字符串。
- 所有时间字段为 ISO 8601 且带时区偏移(timestamptz 传输)。
- 统一响应信封 `{"code": 0, "message": "success", "data": …}`;错误同时携带正确的
HTTP 状态码与稳定业务码。
- Pets 域全部端点强制 Bearer 鉴权(`Authorization: Bearer <accessToken>`)。
## Pets 域新增错误码(追加进既有表,不改号)
| 业务码 | HTTP | 场景 |
| --- | --- | --- |
| 40300 | 403 | PET_ACCESS_DENIED:对可见宠物无相应操作权限(viewer 尝试写等) |
| 40401 | 404 | PET_NOT_FOUND:宠物不存在或调用者不可见(防 ID 枚举,不区分) |
| 40402 | 404 | RECORD_NOT_FOUND:宠物下的记录(体重/疫苗/事件/提醒)不存在 |
| 40902 | 409 | VERSION_CONFLICT:乐观锁版本冲突(PATCH 操作,version 过期) |
| 40903 | 409 | DUPLICATE_VACCINATION:同宠物同疫苗同系列同剂次非 cancelled 记录已存在 |
| 42200 | 422 | BREED_CONSTRAINT_VIOLATIONbreed_id 与 custom_breed_name 未互斥 |
| 42201 | 422 | VACCINATION_STATE_INVALID:疫苗状态机非法迁移或日期约束违反 |
## 权限模型(ADR-015owner/caregiver/viewer 三角色)
# TODO-FREEZE: 等待 T2-03 权限校验实现定型后,补齐每个端点的权限规则描述与错误响应示例。
# 草案默认:owner 全权、caregiver 可读写记录不可改宠物档案、viewer 只读;
# 无权限访问他人宠物返回 404/40401(不可见)或 403/40300(可见但越权)。
servers:
- url: http://127.0.0.1:8082
description: patbond-pet 模块(本地开发,与 user 同服务或独立端口)
tags:
- name: pets
description: 宠物档案 CRUD
- name: dictionaries
description: 品种与疫苗目录(只读)
- name: health-records
description: 体重、疫苗、健康事件、提醒
paths:
/api/v1/pets:
get:
tags: [pets]
summary: 当前用户可见宠物列表
description: |
返回当前用户拥有任何权限(owner/caregiver/viewer)的宠物列表。
# TODO-FREEZE: 列表是否分页待 T2-03 实现时定——量小建议不分页直接返回数组。
operationId: listPets
security:
- bearerAuth: []
responses:
'200':
description: 宠物列表
content:
application/json:
schema:
$ref: '#/components/schemas/PetListEnvelope'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
post:
tags: [pets]
summary: 创建宠物
description: |
创建宠物,创建者自动成为 primary ownerpet_owners 自动写入)。
品种:breed_id 与 custom_breed_name 必须二选一且互斥(ck_pets_breed 约束)。
operationId: createPet
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreatePetRequest'
responses:
'201':
description: 创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/PetEnvelope'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'422':
description: 业务约束违反(breed_id/custom_breed_name 互斥等,code 42200
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
/api/v1/pets/{petId}:
get:
tags: [pets]
summary: 宠物详情
description: |
返回宠物详情及调用者对该宠物的权限角色(role 字段)。
# TODO-FREEZE: 权限拒绝时 403 vs 404 的语义待 T2-03 定型。
operationId: getPet
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 宠物详情
content:
application/json:
schema:
$ref: '#/components/schemas/PetDetailEnvelope'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
patch:
tags: [pets]
summary: 更新宠物档案
description: |
更新宠物档案(名称、品种、性别、生日等)。
请求体必须包含 `version` 乐观锁字段;冲突返回 409/40902。
# TODO-FREEZE: owner/caregiver 权限边界待 T2-03 定型(建议仅 owner 可写档案)。
operationId: updatePet
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdatePetRequest'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
$ref: '#/components/schemas/PetEnvelope'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'403':
description: 无权限更新(code 40300
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'409':
description: 版本冲突(code 40902
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'422':
description: 业务约束违反(code 42200
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
/api/v1/breeds:
get:
tags: [dictionaries]
summary: 品种目录
description: |
品种目录(只读),按 species 过滤。返回 enabled=true 的品种按 sort_order 排序。
operationId: listBreeds
security:
- bearerAuth: []
parameters:
- name: species
in: query
required: false
schema:
type: string
enum: [dog, cat, other]
description: 过滤物种;不传则返回全部
responses:
'200':
description: 品种列表
content:
application/json:
schema:
$ref: '#/components/schemas/BreedListEnvelope'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
/api/v1/pets/{petId}/weights:
get:
tags: [health-records]
summary: 体重记录列表
description: |
体重记录按 measured_at DESC, id DESC 排序,cursor 分页。
operationId: listWeights
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: cursor
in: query
schema:
type: string
description: 上一页返回的 nextCursor,首次不传
responses:
'200':
description: 体重记录分页结果
content:
application/json:
schema:
$ref: '#/components/schemas/WeightListEnvelope'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
post:
tags: [health-records]
summary: 添加体重记录
description: |
添加体重记录。支持 Idempotency-Key(可选但推荐,避免重复提交)。
operationId: createWeight
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
- name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 255
description: 幂等键(可选),相同键重试不产生重复记录
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateWeightRequest'
responses:
'201':
description: 创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/WeightEnvelope'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'403':
description: 无权限添加(viewer 角色,code 40300
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
/api/v1/vaccine-catalog:
get:
tags: [dictionaries]
summary: 疫苗目录
description: |
疫苗目录(只读),按 species 过滤。返回 enabled=true 的疫苗。
operationId: listVaccineCatalog
security:
- bearerAuth: []
parameters:
- name: species
in: query
required: false
schema:
type: string
enum: [dog, cat, other]
responses:
'200':
description: 疫苗目录列表
content:
application/json:
schema:
$ref: '#/components/schemas/VaccineCatalogListEnvelope'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
/api/v1/pets/{petId}/vaccinations:
get:
tags: [health-records]
summary: 疫苗记录列表
description: |
宠物的疫苗记录。不分页或按 administered_on/planned_on 排序分页(待定)。
# TODO-FREEZE: 分页策略待 T2-05 实现时定。
operationId: listVaccinations
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 疫苗记录列表
content:
application/json:
schema:
$ref: '#/components/schemas/VaccinationListEnvelope'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
post:
tags: [health-records]
summary: 创建疫苗记录
description: |
创建疫苗记录(计划或已完成)。
状态机:scheduled 必须带 plannedOncompleted 必须带 administeredOn
同宠物同疫苗同系列同剂次非 cancelled 记录唯一(uq_pet_vaccination_dose)。
# TODO-FREEZE: provider_id/booking_id/certificate_asset_id 按 ADR-010 不开放写入,
# 待 M5/媒体上传流程补齐后再开放,字段在草案保留但标记只读或不出现在请求体。
operationId: createVaccination
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
- name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 255
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateVaccinationRequest'
responses:
'201':
description: 创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/VaccinationEnvelope'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'403':
description: 无权限添加(code 40300
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'409':
description: 同系列同剂次记录已存在(code 40903)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'422':
description: 状态机或日期约束违反(code 42201)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
/api/v1/vaccinations/{vaccinationId}:
patch:
tags: [health-records]
summary: 更新疫苗记录
description: |
更新疫苗记录(状态流转、补充剂次标签、批号等)。
请求体必须包含 `version` 乐观锁;冲突返回 409/40902。
operationId: updateVaccination
security:
- bearerAuth: []
parameters:
- name: vaccinationId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateVaccinationRequest'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
$ref: '#/components/schemas/VaccinationEnvelope'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'403':
description: 无权限更新(code 40300
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'404':
description: 记录不存在(code 40402
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'409':
description: 版本冲突(code 40902
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'422':
description: 状态机或日期约束违反(code 42201)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
/api/v1/pets/{petId}/health-events:
get:
tags: [health-records]
summary: 健康事件时间线
description: |
健康事件按 occurredAt DESC, id DESC 排序,cursor 分页。
operationId: listHealthEvents
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: cursor
in: query
schema:
type: string
responses:
'200':
description: 健康事件分页结果
content:
application/json:
schema:
$ref: '#/components/schemas/HealthEventListEnvelope'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
post:
tags: [health-records]
summary: 添加健康事件
description: |
添加健康事件。六类事件类型:medical/feeding/deworming/grooming/measurement/note。
金额以整数分(amount_cents)传输,非负。
# TODO-FREEZE: provider_id/booking_id 按 ADR-010 不开放写入。
operationId: createHealthEvent
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
- name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 255
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateHealthEventRequest'
responses:
'201':
description: 创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/HealthEventEnvelope'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'403':
description: 无权限添加(code 40300
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
/api/v1/health-events/{eventId}:
patch:
tags: [health-records]
summary: 更新健康事件
description: |
编辑健康事件(标题、备注、金额)。请求体必须包含 `version` 乐观锁。
operationId: updateHealthEvent
security:
- bearerAuth: []
parameters:
- name: eventId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateHealthEventRequest'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
$ref: '#/components/schemas/HealthEventEnvelope'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'403':
description: 无权限更新(code 40300
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'404':
description: 记录不存在(code 40402
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'409':
description: 版本冲突(code 40902
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
/api/v1/pets/{petId}/care-reminders:
get:
tags: [health-records]
summary: 照护提醒列表
description: |
照护提醒列表,按 dueAt 排序。四类提醒类型:deworming/checkup/medication/other。
# TODO-FREEZE: 是否分页、过滤待办(status=pending)的查询参数待 T2-07 实现时定。
operationId: listCareReminders
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 提醒列表
content:
application/json:
schema:
$ref: '#/components/schemas/CareReminderListEnvelope'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
post:
tags: [health-records]
summary: 创建照护提醒
description: |
创建提醒(M2 仅 app 内数据,不做推送,ADR-010 说明)。
operationId: createCareReminder
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateCareReminderRequest'
responses:
'201':
description: 创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/CareReminderEnvelope'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'403':
description: 无权限添加(code 40300
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
/api/v1/care-reminders/{reminderId}:
patch:
tags: [health-records]
summary: 更新提醒状态
description: |
标记提醒完成或忽略(pending → completed/dismissed)。
completed 状态必须写入 completedAtck_care_reminder_completed 约束)。
operationId: updateCareReminder
security:
- bearerAuth: []
parameters:
- name: reminderId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateCareReminderRequest'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
$ref: '#/components/schemas/CareReminderEnvelope'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'403':
description: 无权限更新(code 40300
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'404':
description: 记录不存在(code 40402
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'422':
description: 状态与 completedAt 一致性违反(code 42201 复用)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
/api/v1/pets/{petId}/summary:
get:
tags: [health-records]
summary: 档案聚合摘要
description: |
实时聚合生成档案页摘要:最新体重、疫苗进度、下次接种、当月花费。
# TODO-FREEZE: 等待 T2-08 聚合字段定型——字段命名、月度边界口径(UTC 或指定时区)、
# 疫苗进度分母计算规则(总剂次 vs 已登记剂次)、下次接种取值优先级等。
# 草案字段为占位,冻结前可能变更。
operationId: getPetSummary
security:
- bearerAuth: []
parameters:
- name: petId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 聚合摘要
content:
application/json:
schema:
$ref: '#/components/schemas/PetSummaryEnvelope'
'401':
$ref: '#/components/responses/AccessTokenInvalid'
'404':
description: 宠物不存在或不可见(code 40401)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: 'Authorization: Bearer <accessToken>RS256 JWT'
responses:
ValidationError:
description: 参数校验失败(code 40000
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
examples:
validation:
value: { code: 40000, message: 参数校验失败, data: null }
AccessTokenInvalid:
description: access token 缺失、无效或过期(code 40101)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
examples:
tokenInvalid:
value: { code: 40101, message: token 无效或过期, data: null }
schemas:
ErrorEnvelope:
type: object
required: [code, message]
properties:
code:
type: integer
description: 稳定业务错误码
example: 40401
message:
type: string
example: 宠物不存在或不可见
data:
nullable: true
example: null
# ========== Pets CRUD ==========
Pet:
type: object
required:
- petId
- name
- species
- sex
- status
- createdAt
- updatedAt
- version
properties:
petId:
type: string
format: uuid
name:
type: string
minLength: 1
maxLength: 64
species:
type: string
enum: [dog, cat, other]
breedId:
type: string
format: uuid
nullable: true
description: 品种 ID(与 customBreedName 互斥)
customBreedName:
type: string
nullable: true
minLength: 1
maxLength: 64
description: 自定义品种名(与 breedId 互斥)
sex:
type: string
enum: [male, female, unknown]
birthDate:
type: string
format: date
nullable: true
description: 生日(YYYY-MM-DD
birthDateEstimated:
type: boolean
description: 生日是否为估计值
personality:
type: string
nullable: true
maxLength: 64
description: 性格标签
avatarAssetId:
type: string
format: uuid
nullable: true
description: 头像 asset IDM2 不开放写入,ADR-010
microchipNo:
type: string
nullable: true
description: 芯片号(唯一)
sterilizedOn:
type: string
format: date
nullable: true
description: 绝育日期
status:
type: string
enum: [active, lost, deceased, archived, deleted]
description: 状态(deleted 为软删除)
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
version:
type: integer
description: 乐观锁版本号(PATCH 时必须提交)
PetDetail:
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
required: [myRole]
properties:
myRole:
type: string
enum: [owner, caregiver, viewer]
description: 调用者对该宠物的权限角色
CreatePetRequest:
type: object
required: [name, species, sex]
properties:
name:
type: string
minLength: 1
maxLength: 64
species:
type: string
enum: [dog, cat, other]
breedId:
type: string
format: uuid
description: 品种 ID(与 customBreedName 二选一)
customBreedName:
type: string
minLength: 1
maxLength: 64
description: 自定义品种名(与 breedId 二选一)
sex:
type: string
enum: [male, female, unknown]
birthDate:
type: string
format: date
nullable: true
birthDateEstimated:
type: boolean
default: false
personality:
type: string
maxLength: 64
microchipNo:
type: string
sterilizedOn:
type: string
format: date
UpdatePetRequest:
type: object
required: [version]
properties:
version:
type: integer
description: 当前持有的版本号(乐观锁)
name:
type: string
minLength: 1
maxLength: 64
breedId:
type: string
format: uuid
nullable: true
customBreedName:
type: string
minLength: 1
maxLength: 64
nullable: true
sex:
type: string
enum: [male, female, unknown]
birthDate:
type: string
format: date
nullable: true
birthDateEstimated:
type: boolean
personality:
type: string
maxLength: 64
nullable: true
microchipNo:
type: string
nullable: true
sterilizedOn:
type: string
format: date
nullable: true
status:
type: string
enum: [active, lost, deceased, archived]
description: 状态流转(deleted 不开放)
PetEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
$ref: '#/components/schemas/Pet'
PetDetailEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
$ref: '#/components/schemas/PetDetail'
PetListEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
type: array
items:
$ref: '#/components/schemas/Pet'
# ========== Breeds ==========
Breed:
type: object
required: [breedId, species, code, displayName]
properties:
breedId:
type: string
format: uuid
species:
type: string
enum: [dog, cat, other]
code:
type: string
description: 品种代码(唯一标识)
displayName:
type: string
description: 展示名称
BreedListEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
type: array
items:
$ref: '#/components/schemas/Breed'
# ========== Weights ==========
WeightRecord:
type: object
required: [weightId, petId, weightKg, measuredAt, source, createdAt]
properties:
weightId:
type: string
format: uuid
petId:
type: string
format: uuid
weightKg:
type: number
format: double
minimum: 0.01
maximum: 500
description: 体重(公斤),保留两位小数
measuredAt:
type: string
format: date-time
description: 称重时间
source:
type: string
enum: [manual, clinic, device]
description: 来源
note:
type: string
nullable: true
maxLength: 500
createdAt:
type: string
format: date-time
CreateWeightRequest:
type: object
required: [weightKg, measuredAt]
properties:
weightKg:
type: number
format: double
minimum: 0.01
maximum: 500
measuredAt:
type: string
format: date-time
source:
type: string
enum: [manual, clinic, device]
default: manual
note:
type: string
maxLength: 500
WeightEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
$ref: '#/components/schemas/WeightRecord'
WeightListEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
type: object
required: [items, hasMore]
properties:
items:
type: array
items:
$ref: '#/components/schemas/WeightRecord'
nextCursor:
type: string
nullable: true
description: 下一页游标,无更多时为 null
hasMore:
type: boolean
# ========== Vaccine Catalog ==========
VaccineCatalogItem:
type: object
required: [vaccineId, code, name, species]
properties:
vaccineId:
type: string
format: uuid
code:
type: string
description: 疫苗代码(唯一标识)
name:
type: string
description: 疫苗名称
species:
type: string
enum: [dog, cat, other]
description:
type: string
nullable: true
maxLength: 500
VaccineCatalogListEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
type: array
items:
$ref: '#/components/schemas/VaccineCatalogItem'
# ========== Vaccinations ==========
Vaccination:
type: object
required:
- vaccinationId
- petId
- vaccineId
- seriesKey
- doseNo
- status
- createdAt
- updatedAt
- version
properties:
vaccinationId:
type: string
format: uuid
petId:
type: string
format: uuid
vaccineId:
type: string
format: uuid
seriesKey:
type: string
minLength: 1
maxLength: 64
description: 系列键(区分初次/加强等,与 doseNo 共同唯一)
doseNo:
type: integer
minimum: 1
description: 剂次号
doseLabel:
type: string
nullable: true
maxLength: 64
description: 剂次标签(如"第一针")
status:
type: string
enum: [scheduled, completed, cancelled]
plannedOn:
type: string
format: date
nullable: true
description: 计划接种日期(scheduled 必填)
administeredOn:
type: string
format: date
nullable: true
description: 实际接种日期(completed 必填)
nextDueOn:
type: string
format: date
nullable: true
description: 下次到期日期
manufacturer:
type: string
nullable: true
maxLength: 128
batchNo:
type: string
nullable: true
maxLength: 64
notes:
type: string
nullable: true
maxLength: 1000
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
version:
type: integer
CreateVaccinationRequest:
type: object
required: [vaccineId, seriesKey, doseNo, status]
properties:
vaccineId:
type: string
format: uuid
seriesKey:
type: string
minLength: 1
maxLength: 64
doseNo:
type: integer
minimum: 1
doseLabel:
type: string
maxLength: 64
status:
type: string
enum: [scheduled, completed, cancelled]
plannedOn:
type: string
format: date
description: scheduled 状态必填
administeredOn:
type: string
format: date
description: completed 状态必填
nextDueOn:
type: string
format: date
manufacturer:
type: string
maxLength: 128
batchNo:
type: string
maxLength: 64
notes:
type: string
maxLength: 1000
UpdateVaccinationRequest:
type: object
required: [version]
properties:
version:
type: integer
status:
type: string
enum: [scheduled, completed, cancelled]
plannedOn:
type: string
format: date
nullable: true
administeredOn:
type: string
format: date
nullable: true
nextDueOn:
type: string
format: date
nullable: true
doseLabel:
type: string
maxLength: 64
nullable: true
manufacturer:
type: string
maxLength: 128
nullable: true
batchNo:
type: string
maxLength: 64
nullable: true
notes:
type: string
maxLength: 1000
nullable: true
VaccinationEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
$ref: '#/components/schemas/Vaccination'
VaccinationListEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
type: array
items:
$ref: '#/components/schemas/Vaccination'
# ========== Health Events ==========
HealthEvent:
type: object
required:
- eventId
- petId
- eventType
- occurredAt
- title
- createdByUserId
- createdAt
- updatedAt
- version
properties:
eventId:
type: string
format: uuid
petId:
type: string
format: uuid
eventType:
type: string
enum: [medical, feeding, deworming, grooming, measurement, note]
occurredAt:
type: string
format: date-time
description: 事件发生时间
title:
type: string
minLength: 1
maxLength: 160
notes:
type: string
nullable: true
description: 备注(text 长文本)
amountCents:
type: integer
format: int64
nullable: true
minimum: 0
description: 金额(整数分)
createdByUserId:
type: string
format: uuid
description: 创建者用户 ID
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
version:
type: integer
CreateHealthEventRequest:
type: object
required: [eventType, occurredAt, title]
properties:
eventType:
type: string
enum: [medical, feeding, deworming, grooming, measurement, note]
occurredAt:
type: string
format: date-time
title:
type: string
minLength: 1
maxLength: 160
notes:
type: string
amountCents:
type: integer
format: int64
minimum: 0
description: 金额(整数分)
UpdateHealthEventRequest:
type: object
required: [version]
properties:
version:
type: integer
title:
type: string
minLength: 1
maxLength: 160
notes:
type: string
nullable: true
amountCents:
type: integer
format: int64
minimum: 0
nullable: true
HealthEventEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
$ref: '#/components/schemas/HealthEvent'
HealthEventListEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
type: object
required: [items, hasMore]
properties:
items:
type: array
items:
$ref: '#/components/schemas/HealthEvent'
nextCursor:
type: string
nullable: true
hasMore:
type: boolean
# ========== Care Reminders ==========
CareReminder:
type: object
required:
- reminderId
- petId
- reminderType
- title
- dueAt
- status
- createdAt
- updatedAt
properties:
reminderId:
type: string
format: uuid
petId:
type: string
format: uuid
reminderType:
type: string
enum: [deworming, checkup, medication, other]
title:
type: string
minLength: 1
maxLength: 160
dueAt:
type: string
format: date-time
description: 到期时间
status:
type: string
enum: [pending, completed, dismissed]
completedAt:
type: string
format: date-time
nullable: true
description: 完成时间(completed 状态必填)
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
CreateCareReminderRequest:
type: object
required: [reminderType, title, dueAt]
properties:
reminderType:
type: string
enum: [deworming, checkup, medication, other]
title:
type: string
minLength: 1
maxLength: 160
dueAt:
type: string
format: date-time
UpdateCareReminderRequest:
type: object
required: [status]
properties:
status:
type: string
enum: [pending, completed, dismissed]
completedAt:
type: string
format: date-time
description: 标记 completed 时必填
CareReminderEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
$ref: '#/components/schemas/CareReminder'
CareReminderListEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
type: array
items:
$ref: '#/components/schemas/CareReminder'
# ========== Pet Summary (Aggregation) ==========
# TODO-FREEZE: 等待 T2-08 定型,字段为占位草案
PetSummary:
type: object
properties:
petId:
type: string
format: uuid
latestWeight:
type: object
nullable: true
description: 最新体重
properties:
weightKg:
type: number
format: double
measuredAt:
type: string
format: date-time
vaccinationProgress:
type: object
nullable: true
description: 疫苗进度(口径待定:已完成剂次/总预期剂次)
properties:
completedDoses:
type: integer
description: 已完成剂次
totalDoses:
type: integer
description: 总剂次(口径待定)
nextVaccination:
type: object
nullable: true
description: 下次接种(scheduled 中最近 plannedOn 或最近 nextDueOn,优先级待定)
properties:
vaccineName:
type: string
plannedOn:
type: string
format: date
monthlyExpense:
type: object
nullable: true
description: 当月花费(月度边界口径待定:UTC 月或指定时区月)
properties:
amountCents:
type: integer
format: int64
description: 金额(整数分)
month:
type: string
description: 月份标识(格式待定,如 2026-09)
PetSummaryEnvelope:
type: object
required: [code, message, data]
properties:
code:
type: integer
enum: [0]
message:
type: string
example: success
data:
$ref: '#/components/schemas/PetSummary'