# 到货及出库模块接口对接文档

## 1. 接口概述

到货及出库模块提供了一系列RESTful API接口，用于到货交接单和出库交接单的创建、查询、更新以及与袋牌的关联操作。本文档详细描述了这些接口的使用方法、请求参数和响应格式。

**测试环境请求地址：http://172.232.21.79:5002**
**正式环境请求地址：https://lr.tooexp.com**

### 1.1 接口基础信息

- **到货交接单基础URL**：`http://{服务器地址}:{端口}/api/arrival-handover`
- **出库交接单基础URL**：`http://{服务器地址}:{端口}/api/shipping-handover`
- **请求方式**：POST/GET
- **数据格式**：JSON
- **响应格式**：JSON

### 1.2 状态码说明

| 状态码 | 描述          |
| --- | ----------- |
| 200 | 操作成功        |
| 400 | 请求参数错误或操作失败 |
| 404 | 资源不存在       |
| 500 | 服务器内部错误     |

## 2. 接口详细说明

### 2.1 到货交接单模块

#### 2.1.1 查询到货交接单信息

**接口路径**：`/receipt-query`
**请求方法**：POST
**功能描述**：根据到货编号查询到货交接单详细信息，包括包裹数、已有标签率、到货时间等

##### 请求参数

| 参数名           | 类型     | 必填 | 描述            | 示例值                      |
| ------------- | ------ | -- | ------------- | ------------------------ |
| arrivalNumber | string | 是  | 到货编号（提单号或大箱号） | "TEST1ZX30Y730494260906" |
| callback | string | 否  | JSONP回调函数  | "callback" |

请求体示例：
```json
{
  "arrivalNumber": "TEST1ZX30Y730494260906",
  "callback": null
}
```

##### Mock数据

| 到货编号                   | 包裹数  | 已有标签率 | 到货时间       | 提单号                    | 大箱号               |
| ---------------------- | ---- | ----- | ---------- | ------------------------ | ----------------- |
| TEST1ZX30Y730494260906 | 1200 | 0.8   | 1744032000000 | TEST1ZX30Y730494260906 | testS169-3-20-2-1 |
| TEST1ZX30Y730494260907 | -    | -     | -          | TEST1ZX30Y730494260907 | -                 |

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "packageCount": 1200,
    "labelRate": 0.8,
    "arrivalTime": 1744032000000,
    "billOfLadingNumber": "TEST1ZX30Y730494260906",
    "masterPackageNumber": "testS169-3-20-2-1"
  }
}
```

响应字段说明：
| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| packageCount | int | 包裹总数 |
| labelRate | double | 已有标签率 |
| arrivalTime | long? | 到货时间戳（毫秒，UTC） |
| billOfLadingNumber | string | 提单号 |
| masterPackageNumber | string | 大箱号 |

**失败响应**：

```json
{
  "code": 9999,
  "message": "无预报数据",
  "data": {
    "billOfLadingNumber": "TEST1ZX30Y730494260907",
    "masterPackageNumber": ""
  }
}
```

### 2.2 出库交接单模块

#### 2.2.1 查询出库交接单详细信息

**接口路径**：`/details/{handoverNumber}`
**请求方法**：GET
**功能描述**：根据出库交接单号查询详细信息，包括BOL单号、渠道商、袋牌数量和总包裹数

##### 请求参数

| 参数名            | 类型     | 必填 | 描述           | 示例值          |
| -------------- | ------ | -- | ------------ | ------------ |
| handoverNumber | string | 是  | 出库交接单号（路径参数） | "TESTBOL001" |
| callback | string | 否  | JSONP回调函数  | "callback" |

##### Mock数据

| 出库交接单号     | 渠道商  | 袋牌数量 | 总包裹数 |
| ------------ | ---- | ---- | ---- |
| TESTBOL001 | GOFO | 3    | 150  |
| TESTBOL002 | USPS | 5    | 250  |
| TESTBOL003 | UPS  | 0    | 0    |

##### 请求示例

```
GET /api/shipping-handover/details/TESTBOL001
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "handoverNumber": "TESTBOL001",
    "channel": "GOFO",
    "bagTagCount": 3,
    "totalPackageCount": 150,
    "status": "Draft"
  }
}
```

响应字段说明：
| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| handoverNumber | string | 交接单号 |
| channel | string | 渠道商 |
| bagTagCount | int | 袋牌数量 |
| totalPackageCount | int | 总包裹数 |
| status | string | 状态 |

**失败响应**：

```json
{
  "code": 9999,
  "message": "Shipping handover form not found"
}
```

#### 2.2.2 确认出库交接单

**接口路径**：`/confirm`
**请求方法**：POST
**功能描述**：确认出库交接单，将状态从草稿修改为已出库

##### 请求参数

| 参数名            | 类型       | 必填 | 描述                     | 示例值                                                           |
| -------------- | -------- | -- | ---------------------- | ------------------------------------------------------------- |
| handoverNumber | string   | 是  | 出库交接单号              | "TESTBOL001"                                                  |
| deliveryTime   | long?    | 否  | 出货时间戳（毫秒，UTC）            | 1744032000000                                                 |
| pod            | string   | 是  | POD图片链接，至少包含两张图片，用逗号分隔 | "https://example.com/pod1.jpg,https://example.com/pod2.jpg" |
| callback | string | 否  | JSONP回调函数  | "callback" |

请求体示例：
```json
{
  "handoverNumber": "TESTBOL001",
  "deliveryTime": 1744032000000,
  "pod": "https://example.com/pod1.jpg,https://example.com/pod2.jpg",
  "callback": null
}
```

##### Mock数据

| 出库交接单号     | 操作结果 |
| ------------ | ---- |
| TESTBOL001 | 成功   |
| TESTBOL002 | 成功   |
| TESTBOL003 | 成功   |

##### 请求示例

```
POST /api/shipping-handover/confirm
Content-Type: application/json

{
  "handoverNumber": "TESTBOL001",
  "deliveryTime": 1744032000000,
  "pod": "https://example.com/pod1.jpg,https://example.com/pod2.jpg"
}
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": true
}
```

响应字段说明：
| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| data | bool | 操作结果 |

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

##### 业务规则

1. 一旦执行确认出库操作后，系统不允许对同一交接单再次执行出库操作
2. 每次出库操作至少关联一个袋牌信息
3. POD字段必须至少包含两张图片的S3链接

#### 2.2.3 创建出库交接单

**接口路径**：`/create`
**请求方法**：GET
**功能描述**：创建出库交接单

##### 请求参数

| 参数名            | 类型       | 必填 | 描述           | 示例值                                                           |
| -------------- | -------- | -- | ------------ | ------------------------------------------------------------- |
| HandoverNumber | string   | 否  | 交接单号，为空时自动生成 | "BOL-ORD-GOFO-20260325-001"                                   |
| Channel        | string   | 是  | 渠道           | "GOFO"                                                        |
| DeliveryTime   | long?    | 否  | 交货时间戳（毫秒，UTC） | 1744032000000                                                 |
| POD            | string   | 否  | POD图片链接      | "https://example.com/pod1.jpg,https://example.com/pod2.jpg" |
| Remarks        | string   | 否  | 备注           | "测试备注"                                                        |
| Creator        | string   | 是  | 创建人          | "test_user"                                                  |
| TimeZone       | string   | 是  | 时区           | "America/New_York"                                           |
| callback | string | 否  | JSONP回调函数  | "callback" |

##### 请求示例

```
GET /api/shipping-handover/create?Channel=GOFO&Creator=test_user&TimeZone=America/New_York
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": 1
}
```

响应字段说明：
| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| data | int | 新增记录ID |

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

#### 2.2.4 获取出库交接单列表

**接口路径**：`/list`
**请求方法**：GET
**功能描述**：获取出库交接单列表，支持分页和筛选

##### 请求参数

| 参数名               | 类型       | 必填 | 描述               | 示例值                       |
| ----------------- | -------- | -- | ---------------- | ------------------------- |
| page              | int      | 否  | 页码，默认1           | 1                         |
| pageSize          | int      | 否  | 每页数量，默认10        | 10                        |
| sortBy            | string   | 否  | 排序字段，默认CreatedAt | "CreatedAt"               |
| sortOrder         | string   | 否  | 排序方向，默认desc      | "desc"                    |
| handoverNumber    | string   | 否  | 交接单号             | "BOL-ORD-GOFO-20260325120000" |
| channel           | string   | 否  | 渠道               | "GOFO"                    |
| creator           | string   | 否  | 创建人              | "test_user"              |
| startDeliveryTime | long?    | 否  | 开始交货时间戳（毫秒，UTC）| 1744032000000             |
| endDeliveryTime   | long?    | 否  | 结束交货时间戳（毫秒，UTC）| 1744118400000             |
| callback | string | 否  | JSONP回调函数  | "callback" |

##### 请求示例

```
GET /api/shipping-handover/list?page=1&pageSize=10&channel=GOFO
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "forms": [
      {
        "Id": 1,
        "HandoverNumber": "BOL-ORD-GOFO-20260325120000",
        "BigBagCount": 3,
        "SmallBagCount": 150,
        "Channel": "GOFO",
        "DeliveryTime": 1744032000000,
        "POD": "https://example.com/pod1.jpg",
        "Remarks": "测试备注",
        "Creator": "test_user",
        "CreatedAt": 1744032000000,
        "UpdatedAt": 1744032000000,
        "TimeZone": "America/New_York",
        "Status": 0
      }
    ],
    "totalCount": 1
  }
}
```

响应字段说明：
| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| forms | array | 交接单列表 |
| totalCount | int | 总记录数 |

ShippingHandoverFormEntity 字段说明：
| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| Id | int | 主键ID |
| HandoverNumber | string | 交接单号 |
| BigBagCount | int | 袋牌数量 |
| SmallBagCount | int | 包裹数量 |
| Channel | string | 渠道 |
| DeliveryTime | long? | 交货时间戳（毫秒，UTC） |
| POD | string | POD图片链接 |
| Remarks | string | 备注 |
| Creator | string | 创建人 |
| CreatedAt | long | 创建时间戳（毫秒，UTC） |
| UpdatedAt | long | 更新时间戳（毫秒，UTC） |
| TimeZone | string | 时区 |
| Status | int | 状态（0=草稿，1=已出库） |

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

### 2.3 出库交接单与袋牌关联模块

#### 2.3.1 关联袋牌到出货交接单

**接口路径**：`/bag-tag/associate/{shippingHandoverFormId}`
**请求方法**：POST
**功能描述**：关联袋牌到出货交接单

##### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| shippingHandoverFormId | int | 是 | 出货交接单ID（路径参数） | 1 |
| bagTagIds | List&lt;int&gt; | 是 | 袋牌ID列表（请求体） | [1, 2, 3] |

##### 请求示例

```
POST /api/shipping-handover/bag-tag/associate/1
Content-Type: application/json

[1, 2, 3]
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": true
}
```

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

#### 2.3.2 获取出货交接单关联的袋牌列表

**接口路径**：`/bag-tag/list/{shippingHandoverFormId}`
**请求方法**：GET
**功能描述**：获取出货交接单关联的袋牌列表

##### 请求参数

| 参数名                    | 类型     | 必填 | 描述            | 示例值        |
| ---------------------- | ------ | -- | ------------- | ---------- |
| shippingHandoverFormId | int    | 是  | 出货交接单ID（路径参数） | 1          |
| callback               | string | 否  | JSONP回调函数  | "callback" |

##### 请求示例

```
GET /api/shipping-handover/bag-tag/list/1
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": [
    {
      "Id": 1,
      "TagNumber": "USPS202601271200000001",
      "ChannelName": "USPS",
      "Status": "Closed",
      "Creator": "system",
      "CreatedAt": 1706361600000,
      "OpenedAt": 1706361900000,
      "ClosedAt": 1706363400000
    }
  ]
}
```

BagTagEntity 字段说明：
| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| Id | int | 主键ID |
| TagNumber | string | 袋牌号 |
| ChannelName | string | 渠道名 |
| Status | string | 状态 |
| Creator | string | 创建人 |
| CreatedAt | long | 创建时间戳（毫秒，UTC） |
| OpenedAt | long? | 开袋时间戳（毫秒，UTC） |
| ClosedAt | long? | 封袋时间戳（毫秒，UTC） |

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

#### 2.3.3 从出货交接单中移除袋牌

**接口路径**：`/bag-tag/remove/{relationId}`
**请求方法**：GET
**功能描述**：从出货交接单中移除袋牌

##### 请求参数

| 参数名        | 类型     | 必填 | 描述         | 示例值        |
| ---------- | ------ | -- | ---------- | ---------- |
| relationId | int    | 是  | 关联ID（路径参数） | 1          |
| callback   | string | 否  | JSONP回调函数  | "callback" |

##### 请求示例

```
GET /api/shipping-handover/bag-tag/remove/1
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": true
}
```

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

#### 2.3.4 清空出货交接单的所有袋牌关联

**接口路径**：`/bag-tag/clear/{shippingHandoverFormId}`
**请求方法**：GET
**功能描述**：清空出货交接单的所有袋牌关联

##### 请求参数

| 参数名                    | 类型     | 必填 | 描述            | 示例值        |
| ---------------------- | ------ | -- | ------------- | ---------- |
| shippingHandoverFormId | int    | 是  | 出货交接单ID（路径参数） | 1          |
| callback               | string | 否  | JSONP回调函数  | "callback" |

##### 请求示例

```
GET /api/shipping-handover/bag-tag/clear/1
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": true
}
```

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

#### 2.3.5 统计出货交接单的袋牌数量和包裹数量

**接口路径**：`/bag-tag/count/{shippingHandoverFormId}`
**请求方法**：GET
**功能描述**：统计出货交接单的袋牌数量和包裹数量

##### 请求参数

| 参数名                    | 类型     | 必填 | 描述            | 示例值        |
| ---------------------- | ------ | -- | ------------- | ---------- |
| shippingHandoverFormId | int    | 是  | 出货交接单ID（路径参数） | 1          |
| callback               | string | 否  | JSONP回调函数  | "callback" |

##### 请求示例

```
GET /api/shipping-handover/bag-tag/count/1
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "bagTagCount": 3,
    "packageCount": 150
  }
}
```

响应字段说明：
| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| bagTagCount | int | 袋牌数量 |
| packageCount | int | 包裹数量 |

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

#### 2.3.6 检查袋牌是否已关联到出货交接单

**接口路径**：`/bag-tag/check/{bagTagId}`
**请求方法**：GET
**功能描述**：检查袋牌是否已关联到出货交接单

##### 请求参数

| 参数名      | 类型     | 必填 | 描述         | 示例值        |
| -------- | ------ | -- | ---------- | ---------- |
| bagTagId | int    | 是  | 袋牌ID（路径参数） | 1          |
| callback | string | 否  | JSONP回调函数  | "callback" |

##### 请求示例

```
GET /api/shipping-handover/bag-tag/check/1
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": true
}
```

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

#### 2.3.7 通过袋牌号关联袋牌到出货交接单

**接口路径**：`/bag-tag/associate-by-number/{shippingHandoverFormId}`
**请求方法**：GET
**功能描述**：通过袋牌号关联袋牌到出货交接单

##### 请求参数

| 参数名                    | 类型     | 必填 | 描述            | 示例值                                             |
| ---------------------- | ------ | -- | ------------- | ------------------------------------------------- |
| shippingHandoverFormId | int    | 是  | 出货交接单ID（路径参数） | 1                                                 |
| bagTagNumbers          | string | 是  | 袋牌号列表（逗号分隔）   | "USPS202601271200000001,USPS202601271200000002" |
| callback               | string | 否  | JSONP回调函数  | "callback"                                       |

##### 请求示例

```
GET /api/shipping-handover/bag-tag/associate-by-number/1?bagTagNumbers=USPS202601271200000001,USPS202601271200000002
```

##### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": true
}
```

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

## 3. 接口调用示例

### 3.1 使用cURL调用

#### 查询出库交接单详细信息

```bash
curl -X GET "http://localhost:5002/api/shipping-handover/details/TESTBOL001"
```

#### 创建出库交接单

```bash
curl -X GET "http://localhost:5002/api/shipping-handover/create?Channel=GOFO&Creator=test_user&TimeZone=America/New_York"
```

#### 查询到货交接单信息（POST请求）

```bash
curl -X POST "http://localhost:5002/api/arrival-handover/receipt-query" \
-H "Content-Type: application/json" \
-d '{"arrivalNumber": "TEST1ZX30Y730494260906"}'
```

### 3.2 使用PowerShell调用

#### 查询出库交接单详细信息

```powershell
Invoke-RestMethod -Uri "http://localhost:5002/api/shipping-handover/details/TESTBOL001" `
  -Method GET
```

#### 创建出库交接单

```powershell
Invoke-RestMethod -Uri "http://localhost:5002/api/shipping-handover/create?Channel=GOFO&Creator=test_user&TimeZone=America/New_York" `
  -Method GET
```

#### 查询到货交接单信息（POST请求）

```powershell
$body = @{
  arrivalNumber = "TEST1ZX30Y730494260906"
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://localhost:5002/api/arrival-handover/receipt-query" `
  -Method POST `
  -Body $body `
  -ContentType "application/json"
```

## 4. 注意事项

### 4.1 数据验证

- 渠道不能为空
- 创建人不能为空
- 时区不能为空
- 时间戳均使用UTC时间（毫秒）

### 4.2 性能考虑

- 批量操作时，建议合理控制数据量
- 频繁的接口调用可能会影响系统性能，建议合理控制调用频率

## 5. 常见问题

### 5.1 创建出库交接单失败

**可能原因**：

- 渠道为空
- 创建人为空
- 时区为空

**解决方案**：

- 确保必填参数不为空

### 5.2 查询出库交接单失败

**可能原因**：

- 出库交接单号不存在

**解决方案**：

- 检查出库交接单号是否正确

## 6. 接口版本管理

| 版本   | 变更内容          | 发布日期       |
| ---- | ------------- | ---------- |
| v1.4 | 恢复接口入参时间参数类型为DateTime/string，返回值保持为long类型时间戳 | 2026-05-08 |
| v1.3 | 修改确认出库交接单接口为POST方法 | 2026-05-08 |
| v1.2 | 修改receipt-query接口为POST方法，时间字段改为long类型时间戳，增加响应字段类型说明 | 2026-05-08 |
| v1.1 | 新增查询到货交接单信息接口 | 2026-03-25 |
| v1.0 | 初始版本，包含所有基础接口 | 2026-03-25 |

## 7. 联系信息

如有接口使用问题，请联系系统管理员或开发团队。
