Metadata-Version: 2.5
Name: py-chanjet-toolkit
Version: 4.0.1
Summary: 畅捷通 T+ Python 扩展包 / Chanjet T+ Python Extension - T+ 云 API 调用封装 / Chanjet T+ Cloud API client library
Project-URL: Homepage, https://gitee.com/guolei19850528/py_chanjet_toolkit
Project-URL: Repository, https://gitee.com/guolei19850528/py_chanjet_toolkit
Author-email: 郭磊 <174000902@qq.com>
License: MIT
License-File: LICENSE
Keywords: T+云API,chanjet,chanjet-toolkit,enterprise,soap,tplus,tplus-toolkit,tplus_api,zkhb,畅捷通,畅捷通T+
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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 :: Internet :: WWW/HTTP
Classifier: Topic :: Office/Business
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: httpx<1.0,>=0.24.0
Requires-Dist: pydantic<3.0,>=2.0.0
Provides-Extra: all
Requires-Dist: mkdocs-material>=9.0.0; extra == 'all'
Requires-Dist: mkdocs>=1.5.0; extra == 'all'
Requires-Dist: mypy>=1.10.0; extra == 'all'
Requires-Dist: pre-commit>=3.7.0; extra == 'all'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'all'
Requires-Dist: pytest-cov>=5.0.0; extra == 'all'
Requires-Dist: pytest>=8.0.0; extra == 'all'
Requires-Dist: python-dotenv>=1.0.0; extra == 'all'
Requires-Dist: respx>=0.21.0; extra == 'all'
Requires-Dist: ruff>=0.8.0; extra == 'all'
Provides-Extra: dev
Requires-Dist: mypy>=1.10.0; extra == 'dev'
Requires-Dist: pre-commit>=3.7.0; extra == 'dev'
Requires-Dist: python-dotenv>=1.0.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.0.0; extra == 'docs'
Requires-Dist: mkdocs>=1.5.0; extra == 'docs'
Provides-Extra: test
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
Requires-Dist: pytest>=8.0.0; extra == 'test'
Requires-Dist: python-dotenv>=1.0.0; extra == 'test'
Requires-Dist: respx>=0.21.0; extra == 'test'
Description-Content-Type: text/markdown

# py_chanjet_toolkit

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

[中文](README.md) | [English](README.en.md)

## 📄 文档

- [畅捷通 T+ 官网](https://www.chanjet.com/)
- [httpx](https://www.python-httpx.org/)
- [pydantic](https://docs.pydantic.dev/)
- [uv](https://docs.astral.sh/uv/)

## 📖 项目介绍

`py_chanjet_toolkit` 是一个畅捷通 T+ Python 扩展包，旨在为 Python 开发者提供简洁的 T+ 服务调用接口。当前版本提供 T+ ZKHB Web Service 的 SOAP `GetDataSet` 调用，支持同步和异步请求、响应 XML 转换以及缴费/退款记录过滤。

本项目使用 Python 3.9 及以上版本，基于 `httpx` 和 `pydantic` 构建。客户端通过上下文管理器管理 HTTP 连接，可按需配置 SOAP 1.1/1.2、请求超时时间和 HTTPX 客户端选项。

## 🏗️ 软件架构

```text
py_chanjet_toolkit/
├── src/py_chanjet_toolkit/
│   └── tplus/
│       └── zkhb/
│           ├── __init__.py
│           ├── client.py       # ZKHB SOAP 同步/异步客户端
│           ├── exception.py    # 配置、网络和服务异常
│           ├── request.py      # SOAP 请求及缴费明细 SQL 构造
│           └── response.py    # 响应模型、XML 转换和缴费退款过滤
├── examples/
│   └── tplus/
│       └── zkhb/
│           └── get_dataset.py  # GetDataSet 同步/异步调用示例
└── tests/
    └── tplus/
        └── zkhb/
            ├── conftest.py
            ├── .env.example    # 真实服务集成测试配置模板
            └── test_get_dataset.py
```

### 核心模块说明

#### `tplus.zkhb` 模块 - T+ ZKHB Web Service

| 模块 | 说明 |
|------|------|
| `client.py` | `Client` 和 `AsyncClient`，调用 SOAP `GetDataSet` 并解析服务响应 |
| `request.py` | 构造 SOAP 请求体；`build_charge_fee_items_query_sql` 构造缴费明细查询 SQL |
| `response.py` | `GetDataSetResponse`、`GetDataSetResult`；XML 数据转字典列表，并提供缴费/退款记录过滤 |
| `exception.py` | `ConfigError`、`NetworkError` 和 `ServiceError` |

## 🛠️ 安装教程

### 方式一：使用 uv 安装（推荐）

```bash
uv add py-chanjet-toolkit
```

### 方式二：使用 pip 安装

```bash
pip install py-chanjet-toolkit
```

### 方式三：从源码安装

```bash
git clone https://gitee.com/guolei19850528/py_chanjet_toolkit.git
cd py_chanjet_toolkit
uv sync --all-extras
```

## 📖 使用说明

> ⚠️ 注意：下面的服务地址、接口路径、房间号和查询条件均为示例。请替换为您有权限访问的 T+ ZKHB 服务配置。请勿将真实凭据或内部服务地址提交到代码仓库。

### 1. `tplus.zkhb` 模块 - T+ ZKHB Web Service

该模块通过 SOAP `GetDataSet` 操作执行 SQL 查询。`base_url` 是服务主机地址，`endpoint_path` 是 ASMX 接口路径；可选的 `service_url` 作为 SOAP 请求中的 `url` 参数发送。

#### 1.1 配置客户端

`soap_version` 支持 `"1.1"`（默认）和 `"1.2"`，`timeout` 以秒为单位。`httpx_client_kwargs` 会传递给底层的 HTTPX 客户端，可用于设置 TLS 校验等选项。

```python
from py_chanjet_toolkit.tplus.zkhb.client import Client

BASE_URL = "https://your-server.example"
ENDPOINT_PATH = "/estate/webService/ForcelandEstateService.asmx"

with Client(
    BASE_URL,
    ENDPOINT_PATH,
    soap_version="1.1",
    timeout=30,
    httpx_client_kwargs={"verify": True},
) as client:
    ...
```

客户端会校验 `base_url`、`endpoint_path`、`soap_version` 和超时时间。同步客户端可使用 `with` 自动关闭连接；异步客户端对应使用 `async with`。

#### 1.2 同步查询

可直接传入 SQL 字符串。`get_dataset` 返回 `GetDataSetResponse`；当响应包含数据时，可调用 `to_dict_list()` 将 XML 行数据转为字典列表。

```python
from py_chanjet_toolkit.tplus.zkhb.client import Client

sql = "select 1"

with Client(
    "https://your-server.example",
    "/estate/webService/ForcelandEstateService.asmx",
) as client:
    response = client.get_dataset(sql)

if response.ok and response.data is not None:
    rows = response.data.to_dict_list()
    print(rows)
```

#### 1.3 异步查询

异步客户端提供与同步客户端相同的配置和响应结构，查询时使用 `await`。

```python
import asyncio

from py_chanjet_toolkit.tplus.zkhb.client import AsyncClient


async def main() -> None:
    async with AsyncClient(
        "https://your-server.example",
        "/estate/webService/ForcelandEstateService.asmx",
        soap_version="1.1",
        timeout=30,
    ) as client:
        response = await client.get_dataset("select 1")
        if response.ok and response.data is not None:
            print(response.data.to_dict_list())


asyncio.run(main())
```

#### 1.4 构造缴费明细查询

`build_charge_fee_items_query_sql` 构造缴费主表、房产、收费项目、房间和账单项目的关联查询。可以传入额外查询列、条件和排序子句。请仅在可信来源构造 SQL 条件；示例中对房间号中的单引号进行 SQL 字符串转义。

```python
from py_chanjet_toolkit.tplus.zkhb.request import build_charge_fee_items_query_sql

room_no = "A-001"
escaped_room_no = room_no.replace("'", "''")
sql = build_charge_fee_items_query_sql(
    conditions=f"and rd.RmNo='{escaped_room_no}' and cfi.EDate>='2026-09-14'",
)
print(sql)
```

默认查询列包含收款单、实收金额、收费期间、房间号和收费项目等字段；也可追加列并指定排序：

```python
sql = build_charge_fee_items_query_sql(
    columns="cml.Remark",
    conditions="and cml.EstateID='E001'",
    order_by="order by cml.ChargeTime desc",
)
```

#### 1.5 过滤配对的缴费和退款记录

`filter_charge_fee_items_data` 按 `SDate`、`EDate` 对记录分组，并在同一期间内按金额绝对值一一匹配正、负金额记录。成功配对的缴费和退款记录都会从结果中移除；未匹配记录、金额为零或金额无法解析的记录会保留。

```python
from py_chanjet_toolkit.tplus.zkhb.response import filter_charge_fee_items_data

rows = [
    {"SDate": "2026-01-01", "EDate": "2026-01-31", "ActualAmount": "600.00"},
    {"SDate": "2026-01-01", "EDate": "2026-01-31", "ActualAmount": "-600.00"},
]

remaining_rows = filter_charge_fee_items_data(rows)
print(remaining_rows)  # []
```

#### 1.6 完整示例脚本

项目提供 [GetDataSet 演示脚本](examples/tplus/zkhb/get_dataset.py)，支持同步/异步模式、SQL 查询及缴费/退款过滤。可通过环境变量或命令行参数传入服务配置。

```bash
uv run --extra test python examples/tplus/zkhb/get_dataset.py \
  --base-url "https://your-server.example" \
  --endpoint-path "/estate/webService/ForcelandEstateService.asmx" \
  --room-no "A-001" \
  --start-date "2026-09-14" \
  --mode sync
```

使用异步客户端时，将 `--mode sync` 改为 `--mode async`。也可以设置 `BASE_URL`、`ENDPOINT_PATH`、`SERVICE_URL`、`TEST_ROOM_NO`、`SOAP_VERSION`、`TIMEOUT` 和 `VERIFY_SSL` 环境变量。

#### 1.7 异常处理

| 异常 | 说明 |
|------|------|
| `ConfigError` | 客户端配置无效 |
| `NetworkError` | HTTP 请求未能完成 |
| `ServiceError` | SOAP 响应包含服务端 Fault，或缺少必要的响应元素 |

HTTP 非成功状态会由 HTTPX 的 `raise_for_status()` 报错；其他 XML 解析错误也会明确向调用方抛出。

### 2. 运行测试

运行不需要真实服务连接的测试：

```bash
uv run --extra test pytest tests/tplus/zkhb/test_get_dataset.py -m "not integration"
```

真实服务集成测试需要先配置 `tests/tplus/zkhb/.env`，可参考 `tests/tplus/zkhb/.env.example`。集成测试会访问配置的服务，请确保使用已获授权的测试环境。

## 📜 许可证

本项目基于 [MIT License](LICENSE) 发布。