VWED_server/docs/storage_location_management_development.md
2025-09-09 10:41:27 +08:00

604 lines
18 KiB
Markdown
Raw 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.

# 库位管理开发文档
## 概述
库位管理模块是VWED任务系统的核心组件之一提供对库位基于动作点分层的全面管理功能。本文档详细介绍了库位管理的API接口、内部实现、数据模型以及开发指南。
## 架构概述
### 系统架构
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ API 层 │ │ 服务层 │ │ 数据层 │
│ (Routes) │───▶│ (Services) │───▶│ (Models) │
│ │ │ │ │ │
│ operate_point_ │ │ OperatePoint │ │ OperatePoint │
│ api.py │ │ Service │ │ Layer │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### 核心组件
1. **API路由层** (`routes/operate_point_api.py`): FastAPI路由定义
2. **服务层** (`services/operate_point_service.py`): 业务逻辑处理
3. **数据模型层** (`data/models/`): ORM模型定义
4. **请求/响应模型** (`routes/model/operate_point_model.py`): API数据模型
## 数据模型
### 主要数据表
#### OperatePointLayer (库位层表)
```sql
CREATE TABLE operate_point_layer (
id VARCHAR(255) PRIMARY KEY, -- 库位ID
operate_point_id VARCHAR(255), -- 动作点ID (外键)
layer_index INTEGER, -- 层索引
layer_name VARCHAR(255), -- 库位名称
is_occupied BOOLEAN DEFAULT FALSE, -- 是否占用
is_locked BOOLEAN DEFAULT FALSE, -- 是否锁定
is_disabled BOOLEAN DEFAULT FALSE, -- 是否禁用
is_empty_tray BOOLEAN DEFAULT FALSE, -- 是否空托盘
locked_by VARCHAR(255), -- 锁定者
goods_content TEXT, -- 货物内容
goods_weight INTEGER, -- 货物重量(克)
goods_volume INTEGER, -- 货物体积(立方厘米)
max_weight INTEGER, -- 最大承重(克)
max_volume INTEGER, -- 最大体积(立方厘米)
layer_height INTEGER, -- 层高(毫米)
tags TEXT, -- 标签
description TEXT, -- 描述
config_json JSONB, -- 扩展字段配置
created_at TIMESTAMP, -- 创建时间
updated_at TIMESTAMP, -- 更新时间
is_deleted BOOLEAN DEFAULT FALSE -- 软删除标记
);
```
#### OperatePoint (动作点表)
```sql
CREATE TABLE operate_point (
id VARCHAR(255) PRIMARY KEY, -- 动作点ID
station_name VARCHAR(255), -- 站点名称
scene_id VARCHAR(255), -- 场景ID
storage_area_id VARCHAR(255), -- 库区ID
max_layers INTEGER, -- 最大层数
current_layers INTEGER, -- 当前层数
position_x DECIMAL(10,3), -- X坐标
position_y DECIMAL(10,3), -- Y坐标
position_z DECIMAL(10,3), -- Z坐标
description TEXT, -- 描述
created_at TIMESTAMP, -- 创建时间
updated_at TIMESTAMP, -- 更新时间
is_deleted BOOLEAN DEFAULT FALSE -- 软删除标记
);
```
#### ExtendedProperty (扩展属性表)
```sql
CREATE TABLE extended_property (
id VARCHAR(255) PRIMARY KEY, -- 属性ID
property_key VARCHAR(255) UNIQUE, -- 属性键名
property_name VARCHAR(255), -- 属性名称
property_type VARCHAR(50), -- 属性类型
is_required BOOLEAN DEFAULT FALSE, -- 是否必填
is_enabled BOOLEAN DEFAULT TRUE, -- 是否启用
default_value TEXT, -- 默认值
description TEXT, -- 描述
category VARCHAR(100), -- 分类
validation_rules JSONB, -- 验证规则
options JSONB, -- 选项(select类型使用)
created_at TIMESTAMP, -- 创建时间
updated_at TIMESTAMP, -- 更新时间
is_deleted BOOLEAN DEFAULT FALSE -- 软删除标记
);
```
#### StorageLocationLog (库位操作日志表)
```sql
CREATE TABLE storage_location_log (
id VARCHAR(255) PRIMARY KEY, -- 日志ID
operation_time TIMESTAMP, -- 操作时间
operator VARCHAR(255), -- 操作人
operation_type VARCHAR(100), -- 操作类型
affected_storage_locations JSONB, -- 受影响的库位列表
description TEXT, -- 操作描述
request_data JSONB, -- 请求数据
created_at TIMESTAMP -- 创建时间
);
```
## API接口详解
### 接口分类
库位管理API主要分为以下几类
1. **库位查询接口** - 获取库位列表、详情、状态
2. **库位操作接口** - 更新库位状态、编辑库位信息
3. **扩展属性接口** - 管理自定义属性定义
4. **操作记录接口** - 查询操作历史记录
### 核心接口实现
#### 1. 获取库位列表 (`GET /api/vwed-operate-point/list`)
**实现流程:**
```python
@router.get("/list")
async def get_storage_location_list(
# 查询参数
scene_id: Optional[str] = None,
storage_area_id: Optional[str] = None,
# ... 其他参数
db: Session = Depends(get_db)
):
# 1. 参数验证和构建请求对象
request = StorageLocationListRequest(...)
# 2. 调用服务层方法
result = OperatePointService.get_storage_location_list(db, request)
# 3. 返回格式化响应
return api_response(message="查询成功", data=result)
```
**服务层实现关键点:**
1. **动态查询构建**根据请求参数动态构建SQLAlchemy查询
2. **关联查询优化**只在需要时关联OperatePoint表
3. **自定义排序**:支持层名称和站点名称的智能排序
4. **分页处理**:内存中排序后再分页
5. **数据转换**将ORM对象转换为响应模型
```python
def get_storage_location_list(db: Session, request: StorageLocationListRequest):
# 构建基础查询
query = db.query(OperatePointLayer).filter(
OperatePointLayer.is_deleted == False
)
# 条件过滤
if request.scene_id or request.storage_area_id:
query = query.join(OperatePoint)
# 应用自定义排序
storage_locations = query.all()
if request.layer_name_sort is not None:
storage_locations = _apply_custom_sorting(
storage_locations, request.layer_name_sort, request.station_name_sort
)
# 分页和数据转换
# ...
```
#### 2. 更新库位状态 (`PUT /api/vwed-operate-point/status`)
**支持的操作类型:**
```python
class StorageLocationActionEnum(str, Enum):
OCCUPY = "occupy" # 占用库位
RELEASE = "release" # 释放库位
LOCK = "lock" # 锁定库位
UNLOCK = "unlock" # 解锁库位
ENABLE = "enable" # 启用库位
DISABLE = "disable" # 禁用库位
SET_EMPTY_TRAY = "set_empty_tray" # 设置为空托盘
CLEAR_EMPTY_TRAY = "clear_empty_tray" # 清除空托盘状态
```
**实现流程:**
```python
def update_storage_location_status(db: Session, request: StorageLocationStatusUpdateRequest):
# 1. 查找库位
storage_location = db.query(OperatePointLayer).filter(
OperatePointLayer.layer_name == request.layer_name,
OperatePointLayer.is_deleted == False
).first()
# 2. 验证操作合法性
if not storage_location:
raise ValueError("库位不存在")
# 3. 执行状态更新
old_status = _get_storage_location_status(storage_location)
_apply_action(storage_location, request.action, request.locked_by)
# 4. 记录操作日志
_log_operation(request.layer_name, request.action, request.operator, request.reason)
# 5. 提交事务
db.commit()
return StatusUpdateResult(...)
```
#### 3. 扩展属性管理
扩展属性系统允许用户为库位定义自定义字段,具有以下特点:
1. **动态属性定义**:支持多种数据类型
2. **全局同步**:创建/删除属性会同步到所有库位
3. **验证规则**:支持自定义验证逻辑
4. **UI友好**:支持显示格式和选项配置
**创建扩展属性流程:**
```python
def create_extended_property(db: Session, request: ExtendedPropertyCreateRequest):
# 1. 验证属性名唯一性
existing = db.query(ExtendedProperty).filter(
ExtendedProperty.property_key == request.property_key
).first()
if existing:
raise ValueError("属性键名已存在")
# 2. 创建属性定义
property_obj = ExtendedProperty(...)
db.add(property_obj)
# 3. 同步到所有库位
layers = db.query(OperatePointLayer).filter(
OperatePointLayer.is_deleted == False
).all()
for layer in layers:
config = layer.config_json or {}
config[request.property_key] = request.default_value
layer.config_json = config
# 4. 提交事务
db.commit()
return CreateResult(affected_layers_count=len(layers))
```
## 核心功能详解
### 1. 智能排序功能
系统支持对库位名称和站点名称进行智能排序,能够正确处理字母数字混合的名称:
```python
def _apply_custom_sorting(storage_locations, layer_name_sort, station_name_sort):
"""
智能排序算法:
1. 解析名称中的字母和数字部分
2. 先按字母部分排序
3. 字母相同时按数字部分逐位比较
示例AP1, AP2, AP10, AP11, B1, B2
"""
import re
def _parse_alphanumeric_name(name):
parts = re.findall(r'([A-Za-z]+)|(\d+)', name)
letters = ""
numbers = []
for letter_part, number_part in parts:
if letter_part:
letters += letter_part
elif number_part:
numbers.append(int(number_part))
return (letters.upper(), numbers)
# 实现排序比较逻辑
# ...
```
### 2. 批量操作机制
批量状态更新支持以下特性:
1. **事务一致性**:所有操作在同一事务中执行
2. **部分成功处理**:记录每个库位的操作结果
3. **冲突检测**:检测并报告操作冲突
4. **性能优化**:批量查询和更新
```python
def batch_update_storage_location_status(db: Session, request: BatchStorageLocationStatusUpdateRequest):
results = []
# 批量查询所有库位
storage_locations = db.query(OperatePointLayer).filter(
OperatePointLayer.layer_name.in_(request.layer_names),
OperatePointLayer.is_deleted == False
).all()
# 创建名称到对象的映射
location_map = {sl.layer_name: sl for sl in storage_locations}
# 处理每个库位
for layer_name in request.layer_names:
try:
if layer_name not in location_map:
results.append(OperationResult(
layer_name=layer_name,
success=False,
message="库位不存在"
))
continue
# 执行操作
storage_location = location_map[layer_name]
result = _apply_single_action(storage_location, request.action, request.locked_by)
results.append(result)
except Exception as e:
results.append(OperationResult(
layer_name=layer_name,
success=False,
message=str(e)
))
# 提交事务
db.commit()
return BatchUpdateResult(results=results)
```
### 3. 扩展字段管理
扩展字段系统的设计要点:
1. **存储机制**使用JSONB字段存储扩展属性值
2. **类型系统**支持string、integer、float、boolean、date等类型
3. **验证系统**:支持必填验证、格式验证、范围验证
4. **UI集成**提供显示格式、宽度等UI配置
```python
# 扩展字段配置示例
{
"temperature": {
"value": 25.5,
"type": "float",
"display_format": "{{value}}°C",
"validation": {
"min": -50,
"max": 100
}
},
"product_category": {
"value": "electronics",
"type": "select",
"options": [
{"value": "electronics", "label": "电子产品"},
{"value": "machinery", "label": "机械配件"}
]
}
}
```
### 4. 操作日志系统
所有库位操作都会自动记录到操作日志中:
```python
def _log_storage_location_operation(
layer_names: List[str],
operation_type: str,
operator: str,
description: str,
request_data: Dict = None
):
"""记录库位操作日志"""
log_entry = StorageLocationLog(
id=generate_uuid(),
operation_time=datetime.now(),
operator=operator,
operation_type=operation_type,
affected_storage_locations=layer_names,
description=description,
request_data=request_data or {}
)
db.add(log_entry)
# 注意:不在此处提交事务,由调用方统一提交
```
## 开发指南
### 1. 添加新的操作类型
要添加新的库位操作类型,需要:
1. **更新枚举定义**
```python
class StorageLocationActionEnum(str, Enum):
# 现有操作...
NEW_ACTION = "new_action" # 新操作
```
2. **实现操作逻辑**
```python
def _apply_new_action(storage_location: OperatePointLayer, **kwargs):
"""实现新操作的具体逻辑"""
# 验证前置条件
if not _can_perform_new_action(storage_location):
raise ValueError("无法执行新操作")
# 执行状态更新
storage_location.some_field = new_value
storage_location.updated_at = datetime.now()
return "新操作执行成功"
```
3. **更新操作描述**
```python
def get_action_descriptions():
descriptions = {
# 现有描述...
StorageLocationActionEnum.NEW_ACTION: "执行新操作"
}
return descriptions
```
### 2. 扩展字段类型支持
要添加新的扩展字段类型:
1. **更新类型枚举**
```python
class ExtendedPropertyTypeEnum(str, Enum):
# 现有类型...
CUSTOM_TYPE = "custom_type"
```
2. **实现验证逻辑**
```python
def _validate_custom_type_value(value, property_config):
"""验证自定义类型的值"""
# 实现验证逻辑
pass
```
3. **更新UI配置**
```python
def _get_custom_type_ui_config(property_config):
"""返回自定义类型的UI配置"""
return {
"component": "CustomTypeInput",
"props": {
# UI组件属性
}
}
```
### 3. 性能优化建议
1. **查询优化**
- 合理使用数据库索引
- 避免N+1查询问题
- 使用批量查询替代循环查询
2. **内存管理**
- 大量数据查询时使用分页
- 及时释放不需要的对象引用
- 考虑使用数据流处理
3. **缓存策略**
- 缓存扩展属性配置
- 缓存常用的库位状态查询
- 使用Redis进行分布式缓存
### 4. 错误处理最佳实践
```python
# 统一错误处理模式
try:
# 业务逻辑
result = perform_operation()
return success_response(result)
except ValueError as e:
# 业务逻辑错误(客户端错误)
logger.warning(f"业务逻辑错误: {str(e)}")
return error_response(str(e), 400)
except PermissionError as e:
# 权限错误
logger.warning(f"权限不足: {str(e)}")
return error_response("权限不足", 403)
except Exception as e:
# 系统错误(服务器错误)
logger.error(f"系统错误: {str(e)}", exc_info=True)
return error_response("系统内部错误", 500)
```
### 5. 测试策略
1. **单元测试**
```python
def test_update_storage_location_status():
# 准备测试数据
storage_location = create_test_storage_location()
request = StorageLocationStatusUpdateRequest(
layer_name="test-layer",
action="occupy"
)
# 执行测试
result = OperatePointService.update_storage_location_status(db, request)
# 验证结果
assert result.success == True
assert storage_location.is_occupied == True
```
2. **集成测试**
```python
def test_storage_location_api_integration():
# 测试完整的API调用流程
response = client.put("/api/vwed-operate-point/status", json={
"layer_name": "test-layer",
"action": "occupy"
})
assert response.status_code == 200
assert response.json()["code"] == 200
```
## 部署和维护
### 1. 数据库迁移
当需要修改数据表结构时:
```python
# 创建迁移文件
python scripts/generate_migration.py
# 应用迁移
python scripts/run_migration.py
```
### 2. 监控和日志
关键指标监控:
- API响应时间
- 数据库查询性能
- 错误率统计
- 库位操作频率
日志配置:
```python
# 在utils/logger.py中配置
logger = get_logger("services.operate_point_service")
logger.info("库位状态更新", extra={
"layer_name": layer_name,
"action": action,
"operator": operator
})
```
### 3. 性能调优
数据库优化:
```sql
-- 创建必要的索引
CREATE INDEX idx_operate_point_layer_name ON operate_point_layer(layer_name);
CREATE INDEX idx_operate_point_layer_status ON operate_point_layer(is_occupied, is_locked, is_disabled);
CREATE INDEX idx_storage_location_log_time ON storage_location_log(operation_time);
```
## 总结
库位管理模块是一个功能完整、设计良好的系统组件,提供了:
1. **完整的CRUD操作**:支持库位的查询、创建、更新、删除
2. **灵活的状态管理**:支持多种库位状态操作
3. **可扩展的属性系统**:允许用户定义自定义字段
4. **完整的操作审计**:记录所有操作历史
5. **高性能的查询**:支持复杂查询和智能排序
6. **良好的错误处理**:统一的错误处理和响应格式
该模块为AMR调度系统提供了可靠的库位管理基础支持高并发、高可用的生产环境需求。