# Material Documents - Read, Create

> **API 名称**: Material Documents - Read, Create
> **服务标识**: `API_MATERIAL_DOCUMENT_SRV`
> **版本**: 1.5.0
> **状态**: ACTIVE
> **协议**: OData V2
> **API 地址**: [API_MATERIAL_DOCUMENT_SRV](https://api.sap.com/api/API_MATERIAL_DOCUMENT_SRV/overview)
> **通信场景**: Material Document Integration (SAP_COM_0108)
> **业务对象**: Material Document

---

## 功能说明

This service enables you to retrieve and create material documents, for example, to post a goods receipt for a purchase order or to document the transfer of materials between two storage locations. Additionally, the service allows you to cancel existing material documents or single items. It can be consumed by external systems and user interfaces.

此服务允许您检索和创建物料凭证，例如为采购订单过账收货或记录两个存储地点之间的物料转移。此外，该服务还允许您取消现有的物料凭证或单个行项目。

**主要业务场景:**
- 创建物料凭证（收货、发货、转储等）
- 查询物料凭证抬头和行项目
- 取消物料凭证（整单或单个行项目）
- 管理序列号
- 库存移动过账（移动类型 311、321、561 等）
- 采购订单收货（移动类型 101）
- 生产订单投料/收货

---

## 实体定义

### 实体概览

| # | 实体 | 描述 | 类型 |
|---|------|------|------|
| 1 | `A_MaterialDocumentHeader` | 物料凭证抬头 | 核心实体 |
| 2 | `A_MaterialDocumentItem` | 物料凭证行项目 | 核心实体 |
| 3 | `A_MaterialDocumentSerialNumber` | 物料凭证序列号 | 依赖实体 |

### 实体关系图 (ERD)

```
A_MaterialDocumentHeader (1)
    └── A_MaterialDocumentItem (N)
           └── A_MaterialDocumentSerialNumber (N)
```

**导航属性:**

| 源实体 | 导航属性 | 目标实体 | 多重性 |
|--------|----------|----------|--------|
| `A_MaterialDocumentHeader` | `to_MaterialDocumentItem` | `A_MaterialDocumentItem` | 0..N |
| `A_MaterialDocumentItem` | `to_MaterialDocumentHeader` | `A_MaterialDocumentHeader` | 1 |
| `A_MaterialDocumentItem` | `to_SerialNumbers` | `A_MaterialDocumentSerialNumber` | 0..N |

---

### 1. A_MaterialDocumentHeader（物料凭证抬头）

**主键:** `MaterialDocumentYear`, `MaterialDocument`

> SAP EDM 实体类型: `A_MaterialDocumentHeaderType` | 集合: `A_MaterialDocumentHeader`

| 字段 | 描述 | 类型 | 长度 | 可空 | 示例 |
|------|------|------|------|------|------|
| `MaterialDocumentYear` | 物料凭证年度 | `Edm.String` | 4 | N | `2024` |
| `MaterialDocument` | 物料凭证编号 | `Edm.String` | 10 | N | `5000000001` |
| `InventoryTransactionType` | 库存事务类型 | `Edm.String` | 2 | Y | `WE` |
| `DocumentDate` | 凭证中的单据日期 | `Edm.DateTimeOffset` | - | Y | `2024-01-15T00:00:00Z` |
| `PostingDate` | 过账日期 | `Edm.DateTimeOffset` | - | Y | `2024-01-15T00:00:00Z` |
| `CreationDate` | 创建日期 | `Edm.DateTimeOffset` | - | Y | `2024-01-15T00:00:00Z` |
| `CreationTime` | 创建时间 | `Edm.Time` | - | Y | `PT10H30M00S` |
| `CreatedByUser` | 创建用户 | `Edm.String` | 12 | Y | `USER001` |
| `MaterialDocumentHeaderText` | 凭证抬头文本 | `Edm.String` | 25 | Y | `GR PO 4500000001` |
| `ReferenceDocument` | 参考凭证编号 | `Edm.String` | 16 | Y | `PO-4500000001` |
| `VersionForPrintingSlip` | 打印版本 | `Edm.String` | 1 | Y | `1` |
| `ManualPrintIsTriggered` | 手动打印触发 | `Edm.String` | 1 | Y | `false` |
| `CtrlPostgForExtWhseMgmtSyst` | 外部 WMS 过账控制 | `Edm.String` | 1 | Y | `` |
| `GoodsMovementCode` | 货物移动代码 | `Edm.String` | 2 | Y | `01` |

**导航属性:**
- `to_MaterialDocumentItem` → `A_MaterialDocumentItem[]`

---

### 2. A_MaterialDocumentItem（物料凭证行项目）

**主键:** `MaterialDocumentYear`, `MaterialDocument`, `MaterialDocumentItem`

> SAP EDM 实体类型: `A_MaterialDocumentItemType` | 集合: `A_MaterialDocumentItem`

| 字段 | 描述 | 类型 | 长度 | 可空 | 示例 |
|------|------|------|------|------|------|
| `MaterialDocumentYear` | 物料凭证年度 | `Edm.String` | 4 | N | `2024` |
| `MaterialDocument` | 物料凭证编号 | `Edm.String` | 10 | N | `5000000001` |
| `MaterialDocumentItem` | 行项目号 | `Edm.String` | 4 | N | `0001` |
| `Material` | 物料号 | `Edm.String` | 40 | Y | `M-100` |
| `Plant` | 工厂 | `Edm.String` | 4 | Y | `PL01` |
| `StorageLocation` | 存储位置 | `Edm.String` | 4 | Y | `ST01` |
| `Batch` | 批次号 | `Edm.String` | 10 | Y | `BATCH001` |
| `GoodsMovementType` | 移动类型 | `Edm.String` | 3 | Y | `101` |
| `InventoryStockType` | 库存类型 | `Edm.String` | 2 | Y | `3` |
| `InventoryValuationType` | 库存评估类型 | `Edm.String` | 10 | Y | `0001` |
| `InventorySpecialStockType` | 特殊库存类型 | `Edm.String` | 1 | Y | `` |
| `Supplier` | 供应商 | `Edm.String` | 10 | Y | `10000001` |
| `Customer` | 客户 | `Edm.String` | 10 | Y | `10000005` |
| `SalesOrder` | 销售订单 | `Edm.String` | 10 | Y | `10000001` |
| `SalesOrderItem` | 销售订单行项目 | `Edm.String` | 6 | Y | `000010` |
| `SalesOrderScheduleLine` | 销售订单计划行 | `Edm.String` | 4 | Y | `0001` |
| `PurchaseOrder` | 采购订单 | `Edm.String` | 10 | Y | `4500000001` |
| `PurchaseOrderItem` | 采购订单行项目 | `Edm.String` | 5 | Y | `00010` |
| `WBSElement` | WBS 元素 | `Edm.String` | 24 | Y | `WBS-001` |
| `ManufacturingOrder` | 生产订单 | `Edm.String` | 12 | Y | `10000001` |
| `ManufacturingOrderItem` | 生产订单行项目 | `Edm.String` | 4 | Y | `0001` |
| `GoodsMovementRefDocType` | 货物移动参考文档类型 | `Edm.String` | 1 | Y | `B` |
| `GoodsMovementReasonCode` | 货物移动原因代码 | `Edm.String` | 4 | Y | `0001` |
| `Delivery` | 交货单 | `Edm.String` | 10 | Y | `80000001` |
| `DeliveryItem` | 交货单行项目 | `Edm.String` | 6 | Y | `000010` |
| `AccountAssignmentCategory` | 科目分配类别 | `Edm.String` | 1 | Y | `K` |
| `CostCenter` | 成本中心 | `Edm.String` | 10 | Y | `CC001` |
| `ControllingArea` | 控制范围 | `Edm.String` | 4 | Y | `A000` |
| `CostObject` | 成本对象 | `Edm.String` | 12 | Y | `CO-001` |
| `GLAccount` | 总账科目 | `Edm.String` | 10 | Y | `400000` |
| `FunctionalArea` | 功能范围 | `Edm.String` | 16 | Y | `PROD` |
| `ProfitabilitySegment` | 盈利能力段 | `Edm.String` | 10 | Y | `PS001` |
| `ProfitCenter` | 利润中心 | `Edm.String` | 10 | Y | `PC001` |
| `MasterFixedAsset` | 主固定资产编号 | `Edm.String` | 12 | Y | `1000` |
| `FixedAsset` | 固定资产编号 | `Edm.String` | 4 | Y | `0001` |
| `MaterialBaseUnit` | 物料基本计量单位 | `Edm.String` | 3 | Y | `PC` |
| `QuantityInBaseUnit` | 基本单位数量 | `Edm.Decimal` | 13,3 | Y | `100.000` |
| `EntryUnit` | 输入单位 | `Edm.String` | 3 | Y | `PC` |
| `QuantityInEntryUnit` | 输入单位数量 | `Edm.Decimal` | 13,3 | Y | `100.000` |
| `CompanyCodeCurrency` | 公司代码货币 | `Edm.String` | 5 | Y | `EUR` |
| `GdsMvtExtAmtInCoCodeCrcy` | 货物移动外部金额 | `Edm.Decimal` | 14,3 | Y | `1000.000` |
| `SlsPrcAmtInclVATInCoCodeCrcy` | 销售价税合计 | `Edm.Decimal` | 14,3 | Y | `1190.000` |
| `FiscalYear` | 会计年度 | `Edm.String` | 4 | Y | `2024` |
| `FiscalYearPeriod` | 会计期间 | `Edm.String` | 7 | Y | `2024-01` |
| `FiscalYearVariant` | 会计年度变式 | `Edm.String` | 2 | Y | `K4` |
| `IssgOrRcvgMaterial` | 发出/接收物料 | `Edm.String` | 40 | Y | `M-200` |
| `IssgOrRcvgBatch` | 发出/接收批次 | `Edm.String` | 10 | Y | `BATCH002` |
| `IssuingOrReceivingPlant` | 发出/接收工厂 | `Edm.String` | 4 | Y | `PL02` |
| `IssuingOrReceivingStorageLoc` | 发出/接收存储位置 | `Edm.String` | 4 | Y | `ST02` |
| `IssuingOrReceivingStockType` | 发出/接收库存类型 | `Edm.String` | 2 | Y | `3` |
| `IssgOrRcvgSpclStockInd` | 发出/接收特殊库存标识 | `Edm.String` | 1 | Y | `` |
| `IssuingOrReceivingValType` | 发出/接收评估类型 | `Edm.String` | 10 | Y | `0001` |
| `IsCompletelyDelivered` | 完全交货标记 | `Edm.Boolean` | - | Y | `false` |
| `MaterialDocumentItemText` | 行项目文本 | `Edm.String` | 50 | Y | `Goods receipt for PO` |
| `UnloadingPointName` | 卸货点名称 | `Edm.String` | 25 | Y | `DOCK-01` |
| `ShelfLifeExpirationDate` | 保质期到期日 | `Edm.DateTimeOffset` | - | Y | `2025-01-15T00:00:00Z` |
| `ManufactureDate` | 生产日期 | `Edm.DateTimeOffset` | - | Y | `2024-01-10T00:00:00Z` |
| `SerialNumbersAreCreatedAutomly` | 自动创建序列号 | `Edm.Boolean` | - | Y | `false` |
| `Reservation` | 预留号 | `Edm.String` | 10 | Y | `0000000001` |
| `ReservationItem` | 预留行项目 | `Edm.String` | 4 | Y | `0001` |
| `ReservationIsFinallyIssued` | 预留最终发放 | `Edm.Boolean` | - | Y | `false` |
| `SpecialStockIdfgSalesOrder` | 特殊库存标识销售订单 | `Edm.String` | 10 | Y | `10000001` |
| `SpecialStockIdfgSalesOrderItem` | 特殊库存标识销售订单行 | `Edm.String` | 6 | Y | `000010` |
| `SpecialStockIdfgWBSElement` | 特殊库存标识 WBS 元素 | `Edm.String` | 24 | Y | `WBS-001` |
| `IsAutomaticallyCreated` | 自动创建标记 | `Edm.String` | 1 | Y | `` |
| `MaterialDocumentLine` | 凭证行号 | `Edm.String` | 6 | Y | `000001` |
| `MaterialDocumentParentLine` | 凭证父行号 | `Edm.String` | 6 | Y | `000000` |
| `HierarchyNodeLevel` | 层次节点级别 | `Edm.String` | 2 | Y | `0` |
| `GoodsMovementIsCancelled` | 货物移动已取消标记 | `Edm.Boolean` | - | Y | `false` |
| `ReversedMaterialDocumentYear` | 冲销凭证年度 | `Edm.String` | 4 | Y | `2024` |
| `ReversedMaterialDocument` | 冲销凭证编号 | `Edm.String` | 10 | Y | `5000000002` |
| `ReversedMaterialDocumentItem` | 冲销行项目 | `Edm.String` | 4 | Y | `0001` |
| `ReferenceDocumentFiscalYear` | 参考凭证会计年度 | `Edm.String` | 4 | Y | `2024` |
| `InvtryMgmtRefDocumentItem` | 库存管理参考凭证行 | `Edm.String` | 4 | Y | `0001` |
| `InvtryMgmtReferenceDocument` | 库存管理参考凭证 | `Edm.String` | 10 | Y | `5000000001` |
| `MaterialDocumentPostingType` | 凭证过账类型 | `Edm.String` | 1 | Y | `W` |
| `InventoryUsabilityCode` | 库存可用性代码 | `Edm.String` | 1 | Y | `1` |
| `EWMWarehouse` | EWM 仓库 | `Edm.String` | 4 | Y | `W001` |
| `EWMStorageBin` | EWM 仓位 | `Edm.String` | 18 | Y | `A-01-01` |
| `DebitCreditCode` | 借/贷方代码 | `Edm.String` | 1 | Y | `S` |

**导航属性:**
- `to_MaterialDocumentHeader` → `A_MaterialDocumentHeader`
- `to_SerialNumbers` → `A_MaterialDocumentSerialNumber[]`

---

### 3. A_MaterialDocumentSerialNumber（物料凭证序列号）

**主键:** `MaterialDocumentYear`, `MaterialDocument`, `MaterialDocumentItem`, `SerialNumber`

> SAP EDM 实体类型: `A_SerialNumberMaterialDocumentType` | 集合: `A_SerialNumberMaterialDocument`

| 字段 | 描述 | 类型 | 长度 | 可空 | 示例 |
|------|------|------|------|------|------|
| `MaterialDocumentYear` | 物料凭证年度 | `Edm.String` | 4 | N | `2024` |
| `MaterialDocument` | 物料凭证编号 | `Edm.String` | 10 | N | `5000000001` |
| `MaterialDocumentItem` | 行项目号 | `Edm.String` | 4 | N | `0001` |
| `SerialNumber` | 序列号 | `Edm.String` | 18 | N | `SN-100001` |
| `Material` | 物料号 | `Edm.String` | 40 | Y | `M-100` |
| `Product` | 产品编号 | `Edm.String` | 40 | Y | `M-100` |
| `CustomerSerialNumber` | 客户序列号 | `Edm.String` | 18 | Y | `CUST-SN-001` |
| `QuantityInBaseUnit` | 基本单位数量 | `Edm.Decimal` | - | Y | `1.000` |
| `BaseUnit` | 基本单位 | `Edm.String` | 3 | Y | `PC` |
| `IsDerivedFromMaterial` | 衍生自物料 | `Edm.Boolean` | - | Y | `true` |

**导航属性:**
- `to_MaterialDocumentItem` → `A_MaterialDocumentItem`

---

## API 端点

### 基本 URL

```
https://<server>:<port>/sap/opu/odata/SAP/API_MATERIAL_DOCUMENT_SRV/
```

### GET 请求

#### 查询物料凭证抬头

```
GET /A_MaterialDocumentHeader
GET /A_MaterialDocumentHeader(MaterialDocumentYear='2024',MaterialDocument='5000000001')
```

**GET 查询参数:**

| 参数 | 描述 | 示例 |
|------|------|------|
| `$top` | 限制返回条数 | `$top=10` |
| `$skip` | 跳过条数 | `$skip=20` |
| `$filter` | 筛选条件 | `$filter=PostingDate ge datetime'2024-01-01T00:00:00'` |
| `$orderby` | 排序 | `$orderby=PostingDate desc` |
| `$select` | 选择字段 | `$select=MaterialDocument,PostingDate` |
| `$expand` | 展开导航属性 | `$expand=to_MaterialDocumentItem` |

#### 查询物料凭证行项目

```
GET /A_MaterialDocumentItem
GET /A_MaterialDocumentItem(MaterialDocumentYear='2024',MaterialDocument='5000000001',MaterialDocumentItem='0001')
GET /A_MaterialDocumentHeader(MaterialDocumentYear='2024',MaterialDocument='5000000001')/to_MaterialDocumentItem
```

#### 查询序列号

```
GET /A_SerialNumberMaterialDocument
GET /A_MaterialDocumentItem(MaterialDocumentYear='2024',MaterialDocument='5000000001',MaterialDocumentItem='0001')/to_SerialNumbers
```

### POST 请求

#### 创建物料凭证（Deep Insert - 同时创建抬头+行项目）

```
POST /A_MaterialDocumentHeader
```

**请求体示例（采购订单收货 - 移动类型 101）：**
```json
{
  "MaterialDocumentYear": "2024",
  "MaterialDocument": "",
  "PostingDate": "2024-01-15T00:00:00Z",
  "DocumentDate": "2024-01-15T00:00:00Z",
  "ReferenceDocument": "PO-4500000001",
  "to_MaterialDocumentItem": [
    {
      "MaterialDocumentItem": "0001",
      "Material": "M-100",
      "Plant": "PL01",
      "StorageLocation": "ST01",
      "Batch": "BATCH001",
      "GoodsMovementType": "101",
      "InventoryStockType": "3",
      "QuantityInEntryUnit": 100.000,
      "EntryUnit": "PC",
      "QuantityInBaseUnit": 100.000,
      "MaterialBaseUnit": "PC",
      "PurchaseOrder": "4500000001",
      "PurchaseOrderItem": "00010",
      "to_SerialNumbers": [
        {
          "SerialNumber": "SN-100001",
          "Material": "M-100"
        }
      ]
    }
  ]
}
```

**请求体示例（转储 - 移动类型 311）：**
```json
{
  "MaterialDocumentYear": "2024",
  "MaterialDocument": "",
  "PostingDate": "2024-01-15T00:00:00Z",
  "DocumentDate": "2024-01-15T00:00:00Z",
  "to_MaterialDocumentItem": [
    {
      "MaterialDocumentItem": "0001",
      "Material": "M-100",
      "Plant": "PL01",
      "StorageLocation": "ST01",
      "Batch": "BATCH001",
      "GoodsMovementType": "311",
      "InventoryStockType": "3",
      "QuantityInEntryUnit": 50.000,
      "EntryUnit": "PC",
      "QuantityInBaseUnit": 50.000,
      "MaterialBaseUnit": "PC",
      "IssuingOrReceivingPlant": "PL02",
      "IssuingOrReceivingStorageLoc": "ST02"
    }
  ]
}
```

**创建序列号（向已有行项目添加）：**
```
POST /A_SerialNumberMaterialDocument
```

### Cancel（取消物料凭证）

```
POST /Cancel
```

**请求体示例：**
```json
{
  "MaterialDocumentYear": "2024",
  "MaterialDocument": "5000000001",
  "PostingDate": "2024-01-16T00:00:00Z"
}
```

### CancelItem（取消单个行项目）

```
POST /CancelItem
```

**请求体示例：**
```json
{
  "MaterialDocumentYear": "2024",
  "MaterialDocument": "5000000001",
  "MaterialDocumentItem": "0001",
  "PostingDate": "2024-01-16T00:00:00Z"
}
```

---

## 注意事项

### 1. 认证与授权
- 支持 Basic Auth、OAuth 2.0、x509 证书认证
- 需要通信场景 `SAP_COM_0108`
- 需要分配相应的业务角色和权限

### 2. Deep Insert（深插入）
- 物料凭证只能通过 `POST /A_MaterialDocumentHeader` 创建
- **不支持** 直接 `POST /A_MaterialDocumentItem`
- 行项目和序列号通过导航属性在 Deep Insert 中一并创建

### 3. 移动类型（GoodsMovementType）
| 移动类型 | 描述 | 典型场景 |
|----------|------|----------|
| `101` | 采购订单收货 | GR against PO |
| `102` | 采购订单收货冲销 | Reversal of 101 |
| `201` | 成本中心发货 | Issue to cost center |
| `261` | 生产订单发货 | Issue to production order |
| `311` | 转储 | Transfer posting |
| `321` | 质检到非限制 | Quality to unrestricted |
| `561` | 初始库存导入 | Initial stock entry |
| `601` | 交货单发货 | Delivery issue |

### 4. Cancel（取消）
- `Cancel` 取消整个物料凭证（生成冲销凭证）
- `CancelItem` 取消单个行项目
- 冲销凭证会获得新的凭证编号
- `PostingDate` 参数指定冲销过账日期

### 5. 字段约束
- `MaterialDocument` 创建时留空，系统自动分配
- `MaterialDocumentYear` 为凭证年度，需与过账日期一致
- `MaterialDocumentItem` 建议使用 4 位数字编号
- `QuantityInEntryUnit` 和 `QuantityInBaseUnit` 保留 3 位小数
- `GoodsMovementType` 必须为有效的移动类型
- 批次管理物料必须提供 `Batch` 字段

### 6. 业务规则
- 创建时库存类型 (`InventoryStockType`) 必须与移动类型兼容
- 特殊库存类型 (`InventorySpecialStockType`) 用于寄售、管道等业务
- 序列号管理物料必须提供完整的序列号数据
- 同一凭证中不允许混合不同的参考单据类型
- 取消操作必须在同一会计年度内进行

### 7. HTTP 状态码

| 状态码 | 说明 |
|--------|------|
| `200 OK` | 请求成功 |
| `201 Created` | 创建成功 |
| `204 No Content` | 更新/删除成功 |
| `400 Bad Request` | 请求参数错误 |
| `401 Unauthorized` | 未授权 |
| `403 Forbidden` | 权限不足 |
| `404 Not Found` | 资源未找到 |
| `500 Internal Server Error` | 服务器内部错误 |

---

## PHP SDK: be-lenka/sap-material-document

GitHub: [be-lenka/sap_material-document](https://github.com/be-lenka/sap_material-document)

Composer:
```json
{
  "repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/be-lenka/sap_material-document.git"
    }
  ],
  "require": {
    "be-lenka/sap-material-document": "dev-master"
  }
}
```

使用示例:
```php
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = BeLenka\SAP\MaterialDocument\Configuration::getDefaultConfiguration()
    ->setUsername('YOUR_USERNAME')
    ->setPassword('YOUR_PASSWORD');

$apiInstance = new BeLenka\SAP\MaterialDocument\Api\DocumentHeaderApi(
    new GuzzleHttp\Client(),
    $config
);

// 查询物料凭证抬头
$result = $apiInstance->aMaterialDocumentHeaderGet();
print_r($result);

// 创建物料凭证
$header = new BeLenka\SAP\MaterialDocument\Model\APIMATERIALDOCUMENTSRVAMaterialDocumentHeaderTypeCreate();
$header->setPostingDate(new DateTime('2024-01-15'));
$header->setDocumentDate(new DateTime('2024-01-15'));
// ... set other fields
$result = $apiInstance->aMaterialDocumentHeaderPost($header);
```

---

## SAP Cloud SDK VDM

Java VDM 类: `com.sap.cloud.sdk.s4hana.datamodel.odata.namespaces.materialdocument.MaterialDocumentHeader`

Maven:
```xml
<dependency>
  <groupId>com.sap.cloud.sdk.s4hana</groupId>
  <artifactId>s4hana-api-odata</artifactId>
  <version>4.7.0</version>
</dependency>
```

使用示例:
```java
MaterialDocumentService service = new DefaultMaterialDocumentService();
MaterialDocumentHeader header = service
    .getMaterialDocumentHeaderByKey("2024", "5000000001")
    .execute();
```

---

## 更多信息

- **SAP API Business Hub**: [API_MATERIAL_DOCUMENT_SRV](https://api.sap.com/api/API_MATERIAL_DOCUMENT_SRV/overview)
- **SAP Help Portal**: [Material Documents - Read, Create](https://help.sap.com/docs/SAP_S4HANA_CLOUD/3f57e7df4a114edabffe8b2d581a59ed/d4c919581bc30a02e10000000a44147b.html)
- **OData V2 规范**: [https://www.odata.org/documentation/odata-version-2-0/](https://www.odata.org/documentation/odata-version-2-0/)