Files
吴让宇 c5905a5b1e refactor: 本仓升为唯一源(原 sap-cli 源码仓归档)
方向反转:此前 SKILL.md 是「模板渲染产物」、sap-cli 是源;现 sap-cli 归档,
sap-cli-skill 承接开发与分发,SKILL.md 回归手工维护的正本。

迁移(来自 sap-cli,共 104 文件):
- tests/           692 例测试(15 个文件的内联 sys.path 改指 assets/)
- openspec/        SDD 规格与归档变更(42 文件)
- docs/            开发文档与 ADT 原理(含 dev/CLAUDE.md、AGENTS.md)
- .claude/         rules 副本 + settings.json(供 Claude Code)
- .github/ .hermes/ .pre-commit-config.yaml .editorconfig CLAUDE.md
- scripts/ 保持仅 setup.py(pack_skill.py 已随旧仓归档,不迁)

修复(迁移暴露的真实缺陷):
- assets/pyproject.toml 的 build-backend 写作 `setuptools.backends._legacy:_Backend`,
  该模块在 setuptools 中不存在 → `pip install -e` 从来装不上。改为 build_meta。
  实测:临时 venv 安装成功,sap-cli --help 正常列出 31 个命令
- pyproject readme 指向不存在的 assets/README.md(editable 安装会失败)→ 改内联文本
- pyproject urls 改指 sap-cli-skill

机制调整:
- .github/workflows/ci.yml 适配 assets/ 布局;顶部注明该工作流仅 GitHub 执行,
  本仓在 Gitee 不会自动跑
- pre-commit 增本地测试门禁(Gitee 上真正生效的那道)
- .gitignore 合并旧仓完整规则(保留 log/ 下 md 知识库入库,只忽略运行日志)
- 大文件上限 100KB→1MB(架构图 512KB)

守卫测试 tests/unit/test_repo_guards.py(10 → 18 例):
- SKILL.md 须记录 parser 全部 CLI 命令 / 铁律 1-5 须为真实小节标题 / 示例不得违反铁律 5
- references/ 规则齐备;.claude/rules 与 references 必须一致(实测抓到一次真实漂移)
- VERSION == sapcli.__version__ == README 版本
- 仓内不得再出现 pack_skill.py / skill-src(防废弃流程回潮)

698 tests OK;editable 安装与 CLI 入口经临时 venv 实测通过。
docs/RELEASING.md 重写为单源开发流程。
2026-09-11 00:40:15 +08:00

713 lines
24 KiB
Markdown
Raw Permalink 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.
---
title: ADT 工具集使用指南
created: 2026-05-20
updated: 2026-05-20
tags:
- SAP
- ADT
- REST
- python
- tools
parent: "[[sap-cli/README|SAP ADT 学习笔记总览]]"
---
# ADT 工具集使用指南 — `main.py`
> [!abstract] 概述
> `main.py` 是一个基于 SAP ADT REST API 的命令行工具,支持 **report**、**class**、**function**、**functiongroup**、**interface**、**domain**、**dataelement**、**table**、**tabletype** 等 ABAP 开发对象的创建、信息查询、源代码下载、同步激活和删除操作。
> [!info] 快速查阅
> **命令格式:** `python main.py <命令> --name <名称> --type <类型> [参数]`
>
> | 命令 | 功能 | 完整参数 |
> |------|------|---------|
> | `create` | 创建对象 | `--name` `--type` `[--description]` `[--source]` `[--corr_nr]` |
> | `info` | 查询元数据(状态/描述/时间) | `--name` `--type` |
> | `download` | 下载源码到本地 `.abap` | `--name` `--type` `--path <目录>` |
> | `sync` | 上传源码 → 语法检查 → 激活 | `--name` `--type` `--path <.abap文件>` `[--corr_nr]` |
> | `delete` | 删除对象(需确认) | `--name` `--type` |
>
> **对象类型:** `report` `class` `function` `functiongroup` `interface` `domain` `dataelement` `table` `tabletype`
>
> **sync 流程:** 登录 → 检查/创建对象 → 锁定 → 写入 → 解锁 → 语法检查 → 激活 → 报错则退出(修改后重新执行)
>
> **典型用法:**
> ```bash
> python main.py create --name ZCL_MY_CLASS --type class
> python main.py info --name ZCL_MY_CLASS --type class
> python main.py sync --name ZCL_MY_CLASS --type class --path ./zcl_my_class.abap
> ```
## 1. 前置条件
### 环境要求
- Python 3.10+
- 依赖库:`requests`
### 安装依赖
```bash
pip install requests
```
### 连接配置
连接参数通过配置文件 `config.ini` 管理,位于脚本同目录下:
```ini
[SAP]
host = http://support.learningleader.com.cn:55955
client = 100
user = admin2
password = 654321
```
| 参数 | 说明 |
|------|------|
| `host` | SAP 服务器地址(不含 `/sap/bc/adt` 路径) |
| `client` | SAP 客户端编号 |
| `user` | 登录用户名 |
| `password` | 登录密码 |
> [!tip] 配置文件加载顺序
> 脚本按以下顺序查找配置:
> 1. `--config` 参数指定的文件路径
> 2. 环境变量 `SAP_HOST` / `SAP_CLIENT` / `SAP_USER` / `SAP_PASSWORD`(优先级高于配置文件)
> 3. 当前工作目录下的 `config.ini`
> 4. 脚本同目录下的 `config.ini`
## 2. 对象类型说明
工具支持以下 ABAP 开发对象类型:
| 类型参数 | 对象 | SAP GUI 事务码 | 名称格式 | 支持的操作 |
|---------|------|--------------|---------|----------|
| `report` | 程序 / 报表 | SE38 / SA38 | 直接使用程序名 | 创建、查询、下载、同步、删除 |
| `class` | 类 (ABAP Class) | SE24 | 直接使用类名 | 创建、查询、下载、同步、删除 |
| `function` | 函数模块 (Function Module) | SE37 | `函数组名/函数模块名` | 创建、查询、下载、同步、删除 |
| `functiongroup` | 函数组 (Function Group) | SE37 / SE80 | 直接使用函数组名 | 创建、查询、删除 |
| `interface` | 接口 (ABAP Interface) | SE24 | 直接使用接口名 | 创建、查询、下载、同步、删除 |
| `domain` | 域 (Domain) | SE11 | 直接使用域名 | 创建、同步 |
| `dataelement` | 数据元素 (Data Element) | SE11 | 直接使用元素名 | 创建、同步 |
| `table` | 透明表 (Table) | SE11 | 直接使用表名 | 创建、同步 |
| `tabletype` | 表类型 (Table Type) | SE11 | 直接使用类型名 | 创建、查询 ² |
> [!warning] function 类型的名称格式
> function 类型必须使用 **`函数组名/函数模块名`** 格式,用 `/` 分隔。例如:`ZGROUP/Z_MY_FUNC`
>
> report、class 和 functiongroup 类型直接使用对象名称即可。
## 3. 命令一览
```
python main.py <命令> --name <对象名称> --type <对象类型> [其他参数]
```
| 命令 | 功能 | 必需参数 |
|------|------|---------|
| `create` | 在 SAP 系统创建开发对象 | `--name`, `--type` |
| `info` | 查询对象元数据(描述、激活状态等) | `--name`, `--type` |
| `download` | 从 SAP 下载源代码到本地 | `--name`, `--type`, `--path` |
| `sync` | 上传本地代码到 SAP,语法检查并激活 | `--name`, `--type`, `--path` |
| `delete` | 从 SAP 系统删除对象 | `--name`, `--type` |
## 4. 功能详解
### 4.1 创建开发对象 (`create`)
在 SAP 系统中创建新的开发对象。自动生成默认源代码模板并激活。
#### 执行流程
```
登录 → 检查对象不存在?
├─ 已存在 → 报错停止
└─ 不存在 → 继续
选择传输请求(交互式)
├─ 使用已有请求号(用户输入编号)
├─ 新建请求号(用户提供描述)
└─ 不使用请求号(本地对象)
创建对象 → 写入源代码 → 激活
```
#### 命令格式
```bash
python main.py create --name <对象名> --type <类型> [--description <描述>] [--source <源代码文件>] [--corr_nr <传输请求号>]
```
#### 参数说明
| 参数 | 必需 | 说明 |
|------|------|------|
| `--name` | 是 | 对象名称(function 类型用 `组名/模块名` |
| `--type` | 是 | 对象类型:`report` / `class` / `function` / `functiongroup` |
| `--description` | 否 | 对象描述,默认使用对象名称 |
| `--source` | 否 | 源代码文件路径(`.abap`),不指定则使用内置默认模板 |
| `--corr_nr` | 否 | 直接指定传输请求号(跳过交互选择) |
#### 示例
```bash
# 创建程序(交互式选择传输请求)
python main.py create --name ZMY_REPORT --type report --description "我的报表程序"
# 创建程序(直接指定传输请求号,跳过交互)
python main.py create --name ZMY_REPORT --type report --description "我的报表程序" --corr_nr DEVK901362
# 创建类(使用默认模板)
python main.py create --name ZCL_MY_CLASS --type class --description "我的类"
# 创建函数组
python main.py create --name ZMY_FGROUP --type functiongroup --description "我的函数组"
# 创建函数模块(自动检测并创建函数组)
python main.py create --name ZMY_FGROUP/ZMY_FUNC --type function --description "我的函数模块"
# 使用自定义源代码创建程序
python main.py create --name ZMY_REPORT --type report --source ./my_code.abap
```
#### 输出示例
```
============================================================
SAP ADT 创建开发对象
============================================================
对象类型: 程序(REPORT)
对象名称: ZMY_REPORT
描述: 我的报表程序
→ 检查对象是否存在...
✓ 对象不存在,可以创建
→ 查询可用的传输请求...
找到 2 个可修改的传输请求:
1. DEVK901362 Implement sales validation (所有者: ADMIN2)
2. DEVK901365 Bugfix for invoice printing (所有者: ADMIN2)
3. 新建传输请求
0. 不使用传输请求(本地对象)
请选择 [0-3]: 1
✓ 已选择传输请求: DEVK901362
→ 正在创建对象...
✓ 对象创建成功!
✓ URI: /sap/bc/adt/programs/programs/zmy_report
✓ 源代码已写入并激活 (52 字符)
✓ ZMY_REPORT 创建完成!
类型: 程序(REPORT)
描述: 我的报表程序
```
> [!tip] 传输请求选择
> 创建对象时,脚本会列出所有可修改(Modifiable)状态的传输请求供选择。
> - 选择已有请求:直接输入编号
> - 新建请求:选择"新建传输请求",然后输入描述
> - 本地对象:选择"不使用传输请求",对象将创建在 `$TMP` 包中
> - 非交互模式:使用 `--corr_nr` 参数直接指定传输请求号
#### 默认源代码模板
不指定 `--source` 时,使用以下内置模板:
**report 模板:**
```abap
REPORT ZMY_REPORT.
WRITE: / 'Hello from ZMY_REPORT'.
```
**class 模板:**
```abap
CLASS ZCL_MY_CLASS DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
METHODS: hello.
ENDCLASS.
CLASS ZCL_MY_CLASS IMPLEMENTATION.
METHOD hello.
ENDMETHOD.
ENDCLASS.
```
**function 模板:**
```abap
FUNCTION ZMY_FUNC
EXPORTING
VALUE(EV_RESULT) TYPE STRING.
ev_result = 'hello'.
ENDFUNCTION.
```
> [!tip] 创建函数模块时自动创建函数组
> 创建 function 类型时,脚本会自动检查函数组是否存在。如果不存在,会先自动创建函数组,再创建函数模块。
---
### 4.2 源代码下载 (`download`)
从 SAP 系统下载对象的源代码,保存为本地 `.abap` 文件。
#### 执行流程
```
登录 → 检查对象存在 → 获取源代码 → 保存为 .abap 文件
```
#### 命令格式
```bash
python main.py download --name <对象名> --type <类型> --path <保存目录>
```
#### 示例
```bash
# 下载 report
python main.py download --name ZIDTR_IMPORT_ACCOUNTING_ORDER --type report --path ./output
# 下载 class
python main.py download --name ZCL_MY_CLASS --type class --path ./output
# 下载 function
python main.py download --name ZGROUP/Z_MY_FUNC --type function --path ./output
```
#### 输出
-`--path` 指定目录下生成 **同名小写**`.abap` 文件
- 例如:`--name ZMY_REPORT``./output/zmy_report.abap`
- 如果保存目录不存在,会自动创建
#### 输出示例
```
============================================================
SAP ADT 源代码下载
============================================================
对象类型: 程序(REPORT)
对象名称: ZIDTR_IMPORT_ACCOUNTING_ORDER
保存路径: ./output
→ 正在登录...
✓ 登录成功
→ 检查对象是否存在...
✓ 对象存在
→ 正在下载源代码...
✓ 源代码下载成功! 37655 字符, 1096 行
✓ 文件已保存: ./output\zidtr_import_accounting_order.abap
✅ 下载完成!
文件: ./output\zidtr_import_accounting_order.abap
大小: 37655 字符, 1096 行
```
---
### 4.3 源代码同步激活 (`sync`)
将本地 `.abap` 文件的代码上传到 SAP 系统,进行语法检查并激活。**报错时直接退出,由调用者修改代码后重新执行**。
#### 执行流程
```
登录 → 检查对象是否存在?
├─ 不存在 → 自动创建空对象 → 继续
└─ 存在 → 继续
锁定对象(自动检测传输请求绑定)
├─ 对象已绑定请求号 → 自动使用原请求号
├─ 本地对象($TMP)→ 无需请求号
└─ 需要请求号但未绑定 → 交互选择(已有/新建)
写入 → 解锁
→ 语法检查
├─ 有错误 → 输出错误信息 → 退出(exit code 1
└─ 无错误 → 继续
→ 激活
├─ 成功 → 输出成功信息 → 退出(exit code 0
└─ 失败 → 输出错误信息 → 退出(exit code 1
```
> [!important] 非交互式设计
> 脚本发现语法错误或激活失败时,**不会暂停等待用户输入**,而是直接输出错误信息并以 exit code 1 退出。
> 调用者需要根据错误信息修改本地 `.abap` 文件,然后**重新执行** `sync` 命令。
> [!tip] 传输请求自动检测
> `sync` 命令会**先尝试锁定对象**,通过 SAP 系统返回的信息自动判断传输请求绑定状态:
> - 如果对象已绑定到某个请求号 → 直接使用该请求号,无需用户干预
> - 如果对象是本地对象(`$TMP`)→ 不需要请求号
> - 只有当对象需要请求号但尚未绑定时,才会提示用户选择或新建请求号
#### 命令格式
```bash
python main.py sync --name <对象名> --type <类型> --path <.abap文件路径> [--corr_nr <传输请求号>]
```
#### 参数说明
| 参数 | 必需 | 说明 |
|------|------|------|
| `--name` | 是 | 对象名称(function 类型用 `组名/模块名` |
| `--type` | 是 | 对象类型 |
| `--path` | 是 | 本地源代码文件路径(`.abap` |
| `--corr_nr` | 否 | 直接指定传输请求号(跳过自动检测) |
#### 示例
```bash
# 同步激活 report(自动检测传输请求绑定)
python main.py sync --name ZIDTR_IMPORT_ACCOUNTING_ORDER --type report --path ./zidtr_import_accounting_order.abap
# 同步激活 report(直接指定传输请求号)
python main.py sync --name ZIDTR_IMPORT_ACCOUNTING_ORDER --type report --path ./zidtr_import_accounting_order.abap --corr_nr DEVK901362
# 同步激活 class
python main.py sync --name ZCL_MY_CLASS --type class --path ./zcl_my_class.abap
# 同步激活 function
python main.py sync --name ZGROUP/Z_MY_FUNC --type function --path ./z_my_func.abap
```
#### 输出示例 — 成功(对象已绑定请求号)
```
============================================================
SAP ADT 源代码同步激活
============================================================
对象类型: 类(CLASS)
对象名称: ZCL_MY_CLASS
本地文件: ./zcl_my_class.abap
源代码: 256 字符, 12 行
流程: 检查/创建 → 写入 → 语法检查 → 激活
→ 检查对象是否存在...
✓ 对象存在
────────────────────────────────────────────────────────────
── Step 1/4: 锁定 → 写入 → 解锁 ──
✓ 锁定成功(对象已绑定传输请求: DEVK901362
✓ 源代码写入成功
✓ 解锁成功
── Step 2/4: 语法检查 ──
✓ 语法检查通过
── Step 3/4: 激活对象 ──
✓ 激活成功!
============================================================
✓ ZCL_MY_CLASS 已成功同步并激活!
============================================================
```
#### 输出示例 — 对象未绑定请求号(需要选择)
```
── Step 1/4: 锁定 → 写入 → 解锁 ──
对象需要传输请求号
→ 查询可用的传输请求...
找到 2 个可修改的传输请求:
1. DEVK901362 Implement sales validation (所有者: ADMIN2)
2. DEVK901365 Bugfix for invoice printing (所有者: ADMIN2)
3. 新建传输请求
0. 不使用传输请求(本地对象)
请选择 [0-3]: 1
✓ 已选择传输请求: DEVK901362
✓ 锁定成功(传输请求: DEVK901362
✓ 源代码写入成功
✓ 解锁成功
```
── Step 1/4: 锁定 → 写入 → 解锁 ──
✓ 锁定成功
✓ 源代码写入成功
✓ 解锁成功
── Step 2/4: 语法检查 ──
✓ 语法检查通过
── Step 3/4: 激活对象 ──
✓ 激活成功!
============================================================
✓ ZCL_MY_CLASS 已成功同步并激活!
============================================================
```
#### 输出示例 — 语法检查失败
```
── Step 2/4: 语法检查 ──
✗ 语法检查未通过! 2 个错误, 1 个警告:
[错误] 行 10: Field "XXX" is unknown
[错误] 行 25: Type "ZZZ" is unknown
[警告] 行 5: Unused variable "LV_TEST"
请修改本地文件后重新执行: ./zmy_report.abap
```
> [!tip] 对象不存在时自动创建
> 当同步的目标对象在 SAP 系统中不存在时,脚本会自动创建一个空对象,然后继续执行写入和激活流程。
> 如果自动创建失败,会输出错误信息并退出,此时需要先使用 `create` 命令手动创建。
---
### 4.4 对象信息查询 (`info`)
查询 SAP 系统中开发对象的元数据信息,包括描述、激活状态、开发包、传输请求号、负责人、修改时间等。
#### 执行流程
```
登录 → 查询对象元数据 → 输出信息
```
#### 命令格式
```bash
python main.py info --name <对象名> --type <类型>
```
#### 示例
```bash
# 查询类信息
python main.py info --name ZCL_MY_CLASS --type class
# 查询程序信息
python main.py info --name ZMY_REPORT --type report
# 查询接口信息
python main.py info --name ZIF_MY_INTERFACE --type interface
```
#### 输出示例
```
============================================================
SAP ADT 对象信息查询
============================================================
对象类型: 类(CLASS)
对象名称: ZCL_MY_CLASS
→ 正在登录...
✓ 登录成功
→ 正在查询对象信息...
✓ 查询成功
──────────────────────────────────────────────────
名称: ZCL_MY_CLASS
类型: CLAS/OC
描述: My ABAP Class
状态: ✅ 已激活
负责人: ADMIN2
语言: ZH
开发包: ZSAPILOT
传输请求: DEVK901362
创建者: ADMIN2
修改者: ADMIN2
修改时间: 2026-05-20T12:00:00Z
URI: /sap/bc/adt/oo/classes/zcl_my_class
──────────────────────────────────────────────────
```
> [!tip] 状态说明
> - `✅ 已激活` — 对象处于 active 状态,可在系统中正常使用
> - `⚠️ 未激活` — 对象有未激活的更改,需要执行 `sync` 激活后才能生效
> [!note] 开发包与传输请求
> - **开发包** —— 直接从对象元数据读取
> - **传输请求** —— 纯只读查询系统表 `E071`,显示对象当前所在的未释放请求(多个用逗号分隔)
> - `无` —— 对象不在任何未释放请求中
> - `(无法获取)` —— 无系统表查询权限或查询失败(不影响其余字段输出)
> - `—(非独立传输对象)` —— `include` / `function` 等非独立 R3TR 对象,不单独占用传输请求
> [!note] 支持的对象类型
> `info` 命令支持全部 9 种对象类型:`report`、`class`、`function`、`functiongroup`、`interface`、`domain`、`dataelement`、`table`、`tabletype`。
> `tabletype` 通过 **VIT 端点**`/sap/bc/adt/vit/wb/object_type/ttypda/object_name/{name}`)访问,仅支持元数据查询(`info`),不支持源码读写(`download`/`sync`)和删除操作。
---
### 4.5 源代码删除 (`delete`)
从 SAP 系统中删除指定的开发对象。**删除前需要交互确认**。
#### 执行流程
```
登录 → 检查对象存在 → 确认删除 → 查询传输请求 → 锁定 → 执行删除
```
#### 命令格式
```bash
python main.py delete --name <对象名> --type <类型>
```
#### 示例
```bash
# 删除 report
python main.py delete --name ZMY_OLD_REPORT --type report
# 删除 class
python main.py delete --name ZCL_OBSOLETE --type class
# 删除 function
python main.py delete --name ZGROUP/Z_OLD_FUNC --type function
```
#### 确认提示
```
⚠️ 即将从 SAP 系统中删除: ZMY_OLD_REPORT
类型: 程序(REPORT)
URI: /sap/bc/adt/programs/programs/zmy_old_report
确认删除? (输入 yes 确认):
```
> [!danger] 不可逆操作
> 删除操作不可恢复!请确认对象名称无误后再输入 `yes`。输入其他任何内容均取消操作。
## 5. API 端点映射
不同对象类型对应的 ADT REST API 路径:
| 对象类型 | 对象 URI | 源代码 URI |
|---------|---------|-----------|
| `report` | `/sap/bc/adt/programs/programs/{name}` | `.../source/main` |
| `class` | `/sap/bc/adt/oo/classes/{name}` | `.../source/main` |
| `interface` | `/sap/bc/adt/oo/interfaces/{name}` | `.../source/main` |
| `function` | `/sap/bc/adt/functions/groups/{group}/fmodules/{name}` | `.../source/main` |
| `functiongroup` | `/sap/bc/adt/functions/groups/{name}` | — |
| `domain` | `/sap/bc/adt/ddic/domains/{name}` | `.../source/main` |
| `dataelement` | `/sap/bc/adt/ddic/dataelements/{name}` | `.../source/main` |
| `table` | `/sap/bc/adt/ddic/tables/{name}` | `.../source/main` |
| `tabletype` | `/sap/bc/adt/vit/wb/object_type/ttypda/object_name/{name}` | — (VIT 端点,仅元数据) |
> [!note] URL 中的名称使用小写
> SAP ADT API 的 URL 路径中对象名称通常使用**小写**形式。`tabletype` 例外 — VIT 端点使用**大写**名称以获取完整元数据。脚本已自动处理大小写转换,`--name` 参数输入原始大小写即可。
## 6. 典型工作流
### 场景一:创建新对象 → 修改 → 同步激活
```bash
# Step 1: 创建新程序(自动生成默认代码并激活)
python main.py create --name ZMY_REPORT --type report --description "我的报表"
# Step 2: 下载到本地编辑
python main.py download --name ZMY_REPORT --type report --path ./src
# Step 3: 用编辑器修改 ./src/zmy_report.abap
# Step 4: 同步激活
python main.py sync --name ZMY_REPORT --type report --path ./src/zmy_report.abap
```
### 场景二:下载 → 修改 → 同步激活
```bash
# Step 1: 下载已有对象源代码
python main.py download --name ZMY_REPORT --type report --path ./src
# Step 2: 用编辑器修改 ./src/zmy_report.abap
# Step 3: 同步激活(如果激活失败,修改后重试)
python main.py sync --name ZMY_REPORT --type report --path ./src/zmy_report.abap
```
### 场景三:函数模块开发
```bash
# 创建函数组(如果不存在)
python main.py create --name ZMY_FGROUP --type functiongroup --description "我的函数组"
# 创建函数模块(自动检测函数组,不存在则自动创建)
python main.py create --name ZMY_FGROUP/ZMY_FUNC --type function --description "我的函数"
# 下载并修改
python main.py download --name ZMY_FGROUP/ZMY_FUNC --type function --path ./src
# 同步激活
python main.py sync --name ZMY_FGROUP/ZMY_FUNC --type function --path ./src/zmy_func.abap
```
### 场景四:清理废弃对象
```bash
# 删除废弃程序
python main.py delete --name ZOLD_REPORT --type report
# 删除废弃类
python main.py delete --name ZCL_OBSOLETE --type class
# 删除废弃函数模块
python main.py delete --name ZMY_FGROUP/ZOLD_FUNC --type function
```
## 7. 日志系统
所有 API 请求和响应详细记录在日志文件中:
```
sap-cli/adt_tools.log
```
### 日志内容示例
```
2026-05-20 10:30:00 | INFO | LOGIN: GET http://.../compatibility/graph
2026-05-20 10:30:00 | INFO | LOGIN RESPONSE: HTTP 200
2026-05-20 10:30:00 | INFO | CSRF Token: abCdEfGhIjKlMnOpQrSt...
2026-05-20 10:30:01 | INFO | GET SOURCE: GET .../source/main
2026-05-20 10:30:01 | INFO | GET SOURCE RESPONSE: HTTP 200, 37655 bytes
2026-05-20 10:30:02 | INFO | LOCK: POST .../programs/zmy_report (corrNr=DEVK901362)
2026-05-20 10:30:02 | INFO | LOCK RESPONSE: HTTP 200
2026-05-20 10:30:03 | INFO | SET SOURCE: PUT .../source/main (1024 chars)
2026-05-20 10:30:03 | INFO | ACTIVATE: POST .../activation name=ZMY_REPORT
2026-05-20 10:30:03 | INFO | Activation msg [E] line=10: Field "XXX" unknown
2026-05-20 10:30:03 | INFO | Activation result: FAILED (1 errors)
```
### 排查问题
1. 查看 `adt_tools.log` 中的错误信息
2. 搜索 `FAILED``ERROR` 关键字
3. 激活错误中 `line` 为语句序号,`href` 中的 `start=XXX` 为字符偏移量
4. 结合源代码定位问题位置
## 8. 常见问题
| 问题 | 原因 | 解决方案 |
|------|------|---------|
| 登录失败 HTTP 401 | 用户名或密码错误 | 检查 `config.ini` 中的连接配置 |
| 对象不存在 HTTP 404 | 名称或类型错误 | 确认 `--name``--type` 参数 |
| 对象已存在 HTTP 403 | 创建时对象名冲突 | 使用不存在的对象名或先删除已有对象 |
| 锁定失败 | 对象被其他用户锁定 | 脚本自动处理 corrNr 冲突;如仍失败,等待或联系管理员 |
| 未找到传输请求 | 系统中无 Modifiable 状态的 TR | 在 SAP 中创建传输请求 (SE01/SE09) |
| 激活报语法错误 | 代码有语法问题 | 修改本地文件后重新执行 `sync` 命令 |
| 删除失败 | 权限不足或对象被锁定 | 检查 S_DEVELOP 权限 |
| 环境变量覆盖配置 | 系统环境变量 SAP_HOST 已设置 | 运行前清除:`$env:SAP_HOST=""` |
## 9. 相关笔记
- [[sap-cli/01.ADT架构与通信原理|01.ADT架构与通信原理]] — REST 通信层原理
- [[sap-cli/03.修改代码-原理|03.修改代码-原理]] — 锁定/编辑/激活工作流
- [[sap-cli/07.ADT代码同步工具|07.ADT代码同步工具]] — 早期版本的同步工具
- [[sap-cli/doc/批量同步设计|批量同步设计]] — 项目清单驱动的批量同步方案设计