Metadata-Version: 2.4
Name: ava-data-models
Version: 0.2.3
Summary: AVACloud 业务领域公共 Pydantic v2 数据模型包
Author: AVACloud Team
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/avacloud/ava-data-models
Project-URL: Repository, https://github.com/avacloud/ava-data-models
Project-URL: Issues, https://github.com/avacloud/ava-data-models/issues
Keywords: ava,avacloud,pydantic,models
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic<3.0,>=2.0
Requires-Dist: pydantic-settings<3.0,>=2.0
Requires-Dist: typing-extensions>=4.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: ruff>=0.4.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: black>=24.0; extra == "dev"
Dynamic: license-file

# ava-data-models

AVACloud 业务领域公共 Pydantic v2 数据模型包。

## 项目定位

`ava-data-models` 是 AVACloud 生态下的**公共业务对象模型层**，存放：

- Pydantic v2 业务对象数据模型
- 业务对象公共基类
- ibas 公共枚举与模块本地枚举

**不包含**查询条件、分页、批量操作、通用请求/响应包装，也不包含任何业务查询、校验逻辑、持久化或外部服务调用，作为各智能体项目的公共依赖被引用。

## 技术栈

- Python >= 3.10
- Pydantic v2
- pydantic-settings
- typing-extensions

## 安装

```bash
# 作为依赖安装（发布到 PyPI 后）
pip install ava-data-models

# 本地开发安装
pip install -e ".[dev]"
```

## 目录结构

```text
ava-data-models/
├── pyproject.toml
├── README.md
├── scripts/
│   ├── generate_from_dts.py    # 从 ibas index.d.ts 自动生成模型
│   └── generate_inits.py       # 生成业务模块 __init__.py
├── src/
│   └── ava_data_models/
│       ├── __init__.py         # 根包导出：公共基类 + ibas 公共枚举
│       ├── common/             # 公共基础
│       │   ├── base.py         # BusinessObject / Document / DocumentLine / MasterData / ...
│       │   └── enums.py        # YesNo / BOStatus / DocumentStatus / ApprovalStatus / ...
│       ├── accounting/
│       ├── apparelindustry/
│       ├── approvalprocess/
│       ├── budget/
│       ├── businesspartner/
│       ├── cargos/
│       ├── channels/
│       ├── dealer/
│       ├── documents/
│       ├── equipment/
│       ├── groupfinancemanagement/
│       ├── humanresources/
│       ├── importexport/
│       ├── initialfantasy/
│       ├── integration/
│       ├── invoice/
│       ├── manufacturing/
│       ├── manufacturingcost/
│       ├── manufacturingoutsourcing/
│       ├── manufacturingscheduling/
│       ├── marketingpromotion/
│       ├── masterdata/
│       ├── materials/
│       ├── membercenter/
│       ├── message/
│       ├── product/
│       ├── projectsystem/
│       ├── purchase/
│       ├── qualitycontrol/
│       ├── receiptpayment/
│       ├── reimbursement/
│       ├── reportanalysis/
│       ├── sales/
│       ├── salesopportunity/
│       ├── servicecenter/
│       ├── shopping/
│       ├── store/
│       ├── supplier/
│       ├── taxation/
│       ├── thirdpartyapp/
│       └── ...                 # 每个业务模块独立分包
└── tests/
    └── test_common.py
```

## 命名规范

- 类名：大驼峰（PascalCase），例如 `SalesOrder`、`PurchaseRequestItem`。
- 属性名：小驼峰（camelCase），例如 `docEntry`、`customerCode`，与 ibas TypeScript 声明（*.d.ts）中定义的字段名保持一致。
- 字段类型参考 *.java 源码中声明的 Java 类型，解决 d.ts 中 `number` 不区分 `int`/`decimal` 的问题。
- 枚举类名：去掉 `em` 前缀后首字母大写，例如 `emYesNo` → `YesNo`、`emBOStatus` → `BOStatus`、`emShippingStatus` → `ShippingStatus`。所有枚举继承 `str, Enum`，成员名即字符串值（如 `YesNo.YES == "YES"`、`BOStatus.OPEN == "OPEN"`），便于 LLM 理解和前端展示。ibas 原始数值以注释保留供参考。

## 业务对象基类层次

模型基类与 ibas 业务对象体系对齐：

```text
BusinessObject
├── MasterData          # 对应 ibas.IBOMasterData
├── MasterDataLine      # 对应 ibas.IBOMasterDataLine
├── Document            # 对应 ibas.IBODocument
├── DocumentLine        # 对应 ibas.IBODocumentLine
├── Simple              # 对应 ibas.IBOSimple
└── SimpleLine          # 对应 ibas.IBOSimpleLine
```

- `BusinessObject` 携带 `source_system` / `fetched_at` 跨系统溯源元信息（非 ibas 原有字段，采用 snake_case 风格以避免与业务字段命名冲突）。
- 生成器**仅对直接继承上述 `ibas.IBO*` 接口的类生成模型**。
- 集合壳类（如 `ISalesOrderItems`）不再保留，字段统一用 `list[T]` 表示。

## 使用示例

### 1. 导入公共基础模型与枚举

```python
from ava_data_models import BusinessObject, Document
from ava_data_models import YesNo, BOStatus, DocumentStatus, ApprovalStatus
```

### 2. 导入业务模块模型

```python
from ava_data_models.sales import SalesOrder, SalesOrderItem
from ava_data_models.purchase import PurchaseOrder, PurchaseRequest
from ava_data_models.materials import Material, Warehouse
from ava_data_models.manufacturing import ProductionOrder

# 模块本地枚举也可从模块包直接导入
from ava_data_models.sales import ShippingStatus, AgreementType
```

### 3. 直接解析 ibas API 返回的 camelCase JSON

```python
import json
from ava_data_models.sales import SalesOrder

payload = {
    "docEntry": 10001,
    "docNum": "SO-2024-0001",
    "customerCode": "C001",
    "customerName": "示例客户",
    "documentTotal": 1250.00,
    "canceled": "NO",       # YesNo.NO
    "status": "OPEN",       # BOStatus.OPEN
    "documentStatus": "RELEASED", # DocumentStatus.RELEASED
    "salesOrderItems": [
        {"itemCode": "P001", "quantity": 10.0, "price": 125.0},
    ],
}

order = SalesOrder.model_validate(payload)
print(order.docEntry)         # 10001
print(order.customerCode)     # C001
print(order.documentTotal)    # 1250.0
print(order.canceled)         # "NO" (YesNo.NO)
print(order.status)           # "OPEN" (BOStatus.OPEN)
print(len(order.salesOrderItems))  # 1
```

### 4. 序列化

```python
# 输出 camelCase（与 ibas API 一致），枚举字段序列化为字符串值
order.model_dump()
# {'docEntry': 10001, 'canceled': 'NO', 'status': 'OPEN', ...}

# JSON 字符串
order.model_dump_json()
```

## 模型生成脚本

本项目提供 `scripts/generate_from_dts.py`，可基于本地 `ibas-typescript/test/apps/{module}/index.d.ts` 中的 `bo` 命名空间自动生成对应业务模块的 Pydantic 模型。

### 生成范围

- **业务对象模型**：仅对 `bo` 命名空间中**直接继承 `ibas.IBO*` 业务对象接口**的类生成模型：

| ibas 接口 | Python 基类 |
|---|---|
| `ibas.IBusinessObject` | `BusinessObject` |
| `ibas.IBODocument` | `Document` |
| `ibas.IBODocumentLine` | `DocumentLine` |
| `ibas.IBOMasterData` | `MasterData` |
| `ibas.IBOMasterDataLine` | `MasterDataLine` |
| `ibas.IBOSimple` | `Simple` |
| `ibas.IBOSimpleLine` | `SimpleLine` |

- **ibas 公共枚举**：从 `ibas-typescript/ibas/index.d.ts` 中提取 `emYesNo`、`emBOStatus`、`emDocumentStatus` 等核心枚举，生成到 `common/enums.py`。
- **模块本地枚举**：从各模块 `bo` 命名空间内的 `emXxx` 枚举定义中提取（如 `emShippingStatus`、`emAgreementType`），生成到各模块 `models.py` 顶部。
- 枚举字段类型从 `str` 升级为对应的 `int, Enum` 子类，与 ibas 数值枚举保持一致。

集合壳类（如 `ISalesOrderItems`）不生成独立模型，相关字段统一用 `list[T]` 表示。

### 前提

- 本地存在 ibas 源码目录，默认搜索路径：
  - `/home/niuren.zhu/Codes/ColorCoding`
  - `/home/niuren.zhu/Codes/AVA/Cloud-v2`
- 脚本会在以上路径中查找 `ibas.{module}/ibas.{module}.service/src/main/webapp/index.d.ts` 文件。
- 可通过环境变量覆盖：
  `export IBAS_TEST_APPS=/path/to/ibas-typescript/test/apps`

### 生成全部模块

```bash
python scripts/generate_from_dts.py
python scripts/generate_inits.py
```

### 生成单个模块

```bash
# 修改 generate_from_dts.py 中的 MODULES 列表，仅保留目标模块后执行
python scripts/generate_from_dts.py
python scripts/generate_inits.py
```

### 生成后注意事项

- 生成器为**尽力解析**，复杂的泛型、方法、跨模块引用会降级为 `Any`。
- 集合类（如 `ISalesOrderItems`）会启发式转换为 `list[SalesOrderItem]`。
- 生成后建议人工复核关键字段类型与注释，必要时手工补充或修正。

## 开发

```bash
# 创建虚拟环境
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

# 安装开发依赖
pip install -e ".[dev]"

# 运行测试
pytest tests/ -v

# 代码格式化（可选）
black src tests
ruff check src tests --fix
```

## 发布到 PyPI

```bash
# 1. 安装构建与上传工具
pip install build twine

# 2. 清理历史构建产物
rm -rf dist/ build/

# 3. 构建源码分发包与 Wheel
python -m build

# 4. 先上传到 TestPyPI 验证（可选）
python -m twine upload --repository testpypi dist/*

# 5. 上传到正式 PyPI
python -m twine upload dist/*
```

上传前请确认：

- `pyproject.toml` 中的 `version` 已更新。
- 已配置 PyPI API token（`~/.pypirc` 或通过 `twine login`）。

## 贡献与维护

- 新增业务模块：在 `src/ava_data_models/` 下新增分包，参照现有模块结构编写 `models.py` 与 `__init__.py`。
- 修改公共模型：优先在 `common/` 中定义，并在 `common/__init__.py` 与根包 `__init__.py` 中导出。
- 保持**只存放业务对象模型与枚举**，不引入查询条件、分页、批量操作、业务逻辑、数据库查询或外部 HTTP 调用。

## 许可证

[Apache License 2.0](LICENSE)
