Files
gaokao-volunteer-system/data/orders/__init__.py
coder 9168a10d75 feat(orders): T4.2 DAO 数据访问层 (CRUD + 事务 + 加密 + 状态机)
- data/orders/dao.py (530 lines): OrdersDAO class
  * CRUD: create / get / get_by_external_id / find_by_phone / list / count / stats_by_status / update / delete
  * 事务: transaction() 上下文 + 嵌套深度计数(外层事务中内层不重复 commit)
  * 加密透明化: API 入口 Order dataclass 走明文 PII,DAO 内部 to_db_row/from_db_row 转换
  * 状态机守护: transition_status() 单事务内 UPDATE orders + INSERT order_status_history
    + 时间戳联动 (paid_at/started_at/delivered_at/completed_at COALESCE 保留首次值)
  * 幂等 upsert_by_external_id: 4 种 action 与 data/channel_sync/dao_extension 对齐
  * 防御: update() 显式拒绝 status 字段; _row_factory_ctx() 不污染外部 row_factory
  * 异常: OrderNotFound(LookupError) / DuplicateOrder(ValueError)

- data/orders/tests/test_dao.py (51 cases): 加密透明化、状态机合法/非法路径、
  事务回滚、upsert 4 种 action、状态历史时间线、row_factory 隔离、删除 cascade、
  与 dao_extension 的契约对齐

- data/orders/__init__.py: 导出 OrdersDAO / UpsertResult / StatusChange /
  OrderNotFound / DuplicateOrder

- 验证: data/orders/tests/ 163/163, data/ 386/386, ruff 0 warning, py_compile clean
2026-06-12 16:36:51 +08:00

107 lines
2.1 KiB
Python
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.
"""订单数据模块 (T4.1 + T4.2)
提供:
- SQLite schemaAES-256 加密字段 + 6 态状态机 + 审计表)
- Fernet 加密/解密/索引哈希派生
- 6 态订单状态机
- ``Order`` dataclass + 加密/脱敏序列化
- ``OrdersDAO`` 完整 CRUD + 事务 + 状态机守护(**T4.2**
下游使用
--------
```python
import os
os.environ["GAOKAO_ORDERS_FERNET_KEY"] = "your-secret-here"
from data.orders import (
# schema
apply_schema,
# crypto
encrypt, decrypt, hash_for_index,
# state machine
assert_valid_transition, OrderStatus,
# models
Order, generate_order_id,
# DAO (T4.2)
OrdersDAO, UpsertResult, StatusChange,
OrderNotFound, DuplicateOrder,
)
```
"""
from .crypto import (
ENV_KEY_NAME,
EncryptionError,
MissingEncryptionKey,
constant_time_equals,
decrypt,
derive_key,
encrypt,
get_fernet,
hash_for_index,
)
from .dao import (
DuplicateOrder,
OrderNotFound,
OrdersDAO,
StatusChange,
UpsertResult,
)
from .models import (
DecryptPolicy,
Order,
generate_order_id,
utc_now_iso,
)
from .schema import SCHEMA_SQL, apply_schema, get_schema_version
from .state_machine import (
ALLOWED_TRANSITIONS,
InvalidStateTransition,
OrderStatus,
TERMINAL_STATUSES,
assert_valid_transition,
is_known_status,
is_terminal,
is_valid_transition,
next_states,
)
__all__ = [
# schema
"SCHEMA_SQL",
"apply_schema",
"get_schema_version",
# crypto
"ENV_KEY_NAME",
"EncryptionError",
"MissingEncryptionKey",
"constant_time_equals",
"decrypt",
"derive_key",
"encrypt",
"get_fernet",
"hash_for_index",
# state machine
"ALLOWED_TRANSITIONS",
"InvalidStateTransition",
"OrderStatus",
"TERMINAL_STATUSES",
"assert_valid_transition",
"is_known_status",
"is_terminal",
"is_valid_transition",
"next_states",
# models
"DecryptPolicy",
"Order",
"generate_order_id",
"utc_now_iso",
# DAO
"DuplicateOrder",
"OrderNotFound",
"OrdersDAO",
"StatusChange",
"UpsertResult",
]