# 第 4 章物理决策登记

- 状态：已接受
- 适用模型：`ch04-v1`
- 基线：PostgreSQL 14–18；Pigsty v4.4 L1
- 日期：2026-07-29

## D-004-01 金额

教学域限定为人民币单币种。金额以 `bigint` 保存最小货币单位“分”，并在同一聚合内携带 `currency_code = 'CNY'`；订单行金额由 `unit_price_minor * quantity` 生成。迁移前必须证明旧 `numeric` 值能被 100 整除且不越界。

这不是“整数永远优于 numeric”。若业务支持不同小数位、任意精度计量或复杂汇率，重新评估 `numeric(p,s)` 和货币规则。退款不以负 payment 冒充，留给独立事实。

## D-004-02 时间

事件瞬间使用 `timestamptz(3)`，输入必须携带明确偏移或 IANA 时区语义；验证输出固定 UTC。`created_at` 由 `transaction_timestamp()` 默认产生，`placed_at`、`paid_at`、`cancelled_at` 与 `occurred_at` 由相应业务/提供方事件提供。

`timestamptz` 保存瞬间，不保存用户最初输入的时区名称。若业务必须重建当地民事时间规则，额外保存经批准的 IANA zone name。

## D-004-03 标识

内部引用主键使用 `bigint GENERATED BY DEFAULT AS IDENTITY`。`BY DEFAULT` 允许迁移和确定性教学种子保留历史键；迁移后显式把隐式序列推进到现有最大值。主键约束继续负责唯一性，identity 本身不承担唯一保证。

API 优先暴露 `customer_ref`、`sku`、`order_no`、provider reference 等带作用域的业务标识。若未来需要离线多写者或不可猜测公开 ID，再单独增加并版本化 UUID 方案，不改写现有键的语义。

## D-004-04 状态

订单与支付各自使用 `text` 外键引用 owner-only 查找表，允许转换保存在独立 transition table。`BEFORE UPDATE OF status` 触发器拒绝图外边，并通过固定 `search_path` 的 `SECURITY DEFINER` 函数让无权访问 `shop_private` 的 runtime role 也能安全执行转换。

状态允许值、允许边和状态伴随字段是三层规则：外键限制值域，触发器限制边，行级 `CHECK` 维护时间/失败原因。订单金额与支付总额等跨表不变量仍未由本章解决，进入并发与数据库逻辑章节。

## D-004-05 文本

业务键采用 `text`，由命名 `CHECK` 明确 ASCII 格式；演示 email 在写入前规范为小写 ASCII。人类语言字段保持 Unicode 文本，不把 `lower()` 当作全球通用身份规则。需要大小写/重音不敏感唯一性时，必须先定义 Unicode 正规化、ICU/citext 选择、排序规则版本与索引升级策略。

## D-004-06 半结构化

v1 不在核心交易关系中增加 array 或 JSONB。订单行、状态和支付是需要独立约束、引用和更新的事实，拆表优于把它们藏入文档。范围类型只在隔离实验中表达预订时段，并用排他约束证明“不重叠”规则。

## D-004-07 分区

v1 暂不分区。完整理由、触发条件与复查材料见 [`partition-adr.md`](partition-adr.md)。第 26 章以生产量级数据重新评估。
