#!/usr/bin/env python # -*- coding: utf-8 -*- """ 动作点管理相关模型 用于处理动作点和库位的管理操作 """ from typing import Optional, List, Dict, Any from pydantic import BaseModel, Field from enum import Enum from datetime import datetime from data.models.extended_property import ExtendedPropertyTypeEnum class StorageAreaTypeEnum(str, Enum): """库区类型枚举""" GENERAL = "general" DENSE = "dense" 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" # 清除空托盘状态 class OperatePointLayerInfo(BaseModel): """动作点分层信息""" id: str = Field(..., description="层ID") layer_index: int = Field(..., description="层索引") layer_name: Optional[str] = Field(None, description="层名称") is_occupied: bool = Field(..., description="是否占用") is_locked: bool = Field(..., description="是否锁定") is_disabled: bool = Field(..., description="是否禁用") is_empty_tray: bool = Field(..., description="是否空托盘") goods_content: str = Field(..., description="货物内容") goods_weight: Optional[int] = Field(None, description="货物重量(克)") goods_volume: Optional[int] = Field(None, description="货物体积(立方厘米)") max_weight: Optional[int] = Field(None, description="最大承重(克)") max_volume: Optional[int] = Field(None, description="最大体积(立方厘米)") layer_height: Optional[int] = Field(None, description="层高(毫米)") locked_by: Optional[str] = Field(None, description="锁定者") tags: Optional[str] = Field(None, description="标签") description: Optional[str] = Field(None, description="层描述") goods_stored_at: Optional[datetime] = Field(None, description="货物存放时间") goods_retrieved_at: Optional[datetime] = Field(None, description="货物取出时间") last_access_at: Optional[datetime] = Field(None, description="最后访问时间") # 库位列表相关模型 class StorageLocationInfo(BaseModel): """库位信息(基于动作点分层)""" # 库位基本信息 id: str = Field(..., description="库位ID(层ID)") layer_index: int = Field(..., description="层索引") layer_name: Optional[str] = Field(None, description="层名称") # 库位状态 is_occupied: bool = Field(..., description="是否占用") is_locked: bool = Field(..., description="是否锁定") is_disabled: bool = Field(..., description="是否禁用") is_empty_tray: bool = Field(..., description="是否空托盘") locked_by: Optional[str] = Field(None, description="锁定者") # 货物信息 goods_content: str = Field(..., description="货物内容") goods_weight: Optional[int] = Field(None, description="货物重量(克)") goods_volume: Optional[int] = Field(None, description="货物体积(立方厘米)") goods_stored_at: Optional[datetime] = Field(None, description="货物存放时间") goods_retrieved_at: Optional[datetime] = Field(None, description="货物取出时间") last_access_at: Optional[datetime] = Field(None, description="最后访问时间") # 库位规格 max_weight: Optional[int] = Field(None, description="最大承重(克)") max_volume: Optional[int] = Field(None, description="最大体积(立方厘米)") layer_height: Optional[int] = Field(None, description="层高(毫米)") # 扩展信息 tags: Optional[str] = Field(None, description="标签") description: Optional[str] = Field(None, description="库位描述") created_at: Optional[datetime] = Field(None, description="创建时间") updated_at: Optional[datetime] = Field(None, description="更新时间") # 扩展字段 extended_fields: Optional[Dict[str, Any]] = Field(None, description="扩展字段") # 动作点信息(直接平铺) operate_point_id: Optional[str] = Field(None, description="所属动作点ID") station_name: Optional[str] = Field(None, description="动作站点名称") scene_id: Optional[str] = Field(None, description="场景ID") storage_area_id: Optional[str] = Field(None, description="所属库区ID") storage_area_type: Optional[str] = Field(None, description="库区类型") area_name: Optional[str] = Field(None, description="库区名称") max_layers: Optional[int] = Field(None, description="最大层数") current_layers: Optional[int] = Field(None, description="当前使用层数") position_x: Optional[int] = Field(None, description="X坐标") position_y: Optional[int] = Field(None, description="Y坐标") position_z: Optional[int] = Field(None, description="Z坐标") operate_point_description: Optional[str] = Field(None, description="动作点描述") class StorageLocationListRequest(BaseModel): """库位列表查询请求""" scene_id: Optional[str] = Field(None, description="场景ID") storage_area_id: Optional[str] = Field(None, description="库区ID") station_name: Optional[str] = Field(None, description="站点名称(支持模糊搜索)") layer_name: Optional[str] = Field(None, description="库位名称(支持模糊搜索)") is_disabled: Optional[bool] = Field(None, description="是否禁用") is_occupied: Optional[bool] = Field(None, description="是否占用") is_locked: Optional[bool] = Field(None, description="是否锁定") is_empty_tray: Optional[bool] = Field(None, description="是否空托盘") include_operate_point_info: bool = Field(True, description="是否包含动作点信息") include_extended_fields: bool = Field(True, description="是否包含扩展字段") page: int = Field(1, ge=1, description="页码") page_size: int = Field(20, ge=1, le=100, description="每页数量") class StorageLocationListResponse(BaseModel): """库位列表查询响应""" total: int = Field(..., description="总数量") page: int = Field(..., description="当前页码") page_size: int = Field(..., description="每页数量") total_pages: int = Field(..., description="总页数") storage_locations: List[StorageLocationInfo] = Field(..., description="库位列表") class StorageLocationStatistics(BaseModel): """库位统计信息""" total_storage_locations: int = Field(..., description="总库位数") occupied_storage_locations: int = Field(..., description="已占用库位数") available_storage_locations: int = Field(..., description="可用库位数") disabled_storage_locations: int = Field(..., description="禁用库位数") locked_storage_locations: int = Field(..., description="锁定库位数") empty_tray_storage_locations: int = Field(..., description="空托盘库位数") dense_area_storage_locations: int = Field(..., description="密集库区库位数") general_area_storage_locations: int = Field(..., description="一般库区库位数") occupancy_rate: float = Field(..., description="占用率") availability_rate: float = Field(..., description="可用率") # 库位状态管理相关模型 class StorageLocationStatusUpdateRequest(BaseModel): """库位状态更新请求""" layer_name: str = Field(..., description="库位名称") action: StorageLocationActionEnum = Field(..., description="操作类型") locked_by: Optional[str] = Field(None, description="锁定者(锁定操作时必填)") reason: Optional[str] = Field(None, description="操作原因") class StorageLocationStatusUpdateResponse(BaseModel): """库位状态更新响应""" layer_name: str = Field(..., description="库位名称") action: StorageLocationActionEnum = Field(..., description="执行的操作") success: bool = Field(..., description="操作是否成功") message: str = Field(..., description="操作结果消息") new_status: Dict[str, Any] = Field(..., description="更新后的状态信息") class BatchStorageLocationStatusUpdateRequest(BaseModel): """批量库位状态更新请求""" layer_names: List[str] = Field(..., description="库位名称列表") action: StorageLocationActionEnum = Field(..., description="操作类型") locked_by: Optional[str] = Field(None, description="锁定者(锁定操作时必填)") reason: Optional[str] = Field(None, description="操作原因") class BatchStorageLocationStatusUpdateResponse(BaseModel): """批量库位状态更新响应""" total_count: int = Field(..., description="总操作数量") success_count: int = Field(..., description="成功操作数量") failed_count: int = Field(..., description="失败操作数量") results: List[StorageLocationStatusUpdateResponse] = Field(..., description="详细操作结果列表") # 扩展属性管理相关模型 class ExtendedPropertyCreateRequest(BaseModel): """扩展属性创建请求""" property_name: str = Field(..., description="属性名称(唯一标识)", min_length=1, max_length=200) property_type: ExtendedPropertyTypeEnum = Field(ExtendedPropertyTypeEnum.STRING, description="属性类型") is_required: bool = Field(False, description="是否必填") is_enabled: bool = Field(True, description="是否启用") description: Optional[str] = Field(None, description="属性描述") placeholder: Optional[str] = Field(None, description="输入提示", max_length=500) default_value: Optional[str] = Field(None, description="默认值") options: Optional[List[Dict[str, Any]]] = Field(None, description="选项值(用于select和multiselect类型)") validation_rules: Optional[Dict[str, Any]] = Field(None, description="验证规则") category: Optional[str] = Field(None, description="属性分类", max_length=100) sort_order: int = Field(0, description="排序顺序") display_width: int = Field(200, description="显示宽度(像素)") display_format: Optional[str] = Field(None, description="显示格式", max_length=100) class ExtendedPropertyInfo(BaseModel): """扩展属性信息""" id: str = Field(..., description="属性ID") property_name: str = Field(..., description="属性名称(唯一标识)") property_type: ExtendedPropertyTypeEnum = Field(..., description="属性类型") is_required: bool = Field(..., description="是否必填") is_enabled: bool = Field(..., description="是否启用") description: Optional[str] = Field(None, description="属性描述") placeholder: Optional[str] = Field(None, description="输入提示") default_value: Optional[str] = Field(None, description="默认值") options: Optional[List[Dict[str, Any]]] = Field(None, description="选项值") validation_rules: Optional[Dict[str, Any]] = Field(None, description="验证规则") category: Optional[str] = Field(None, description="属性分类") sort_order: int = Field(..., description="排序顺序") display_width: int = Field(..., description="显示宽度(像素)") display_format: Optional[str] = Field(None, description="显示格式") created_at: datetime = Field(..., description="创建时间") updated_at: datetime = Field(..., description="更新时间") class ExtendedPropertyCreateResponse(BaseModel): """扩展属性创建响应""" id: str = Field(..., description="创建的属性ID") property_name: str = Field(..., description="属性名称(唯一标识)") message: str = Field(..., description="创建结果消息") class ExtendedPropertyListRequest(BaseModel): """扩展属性列表查询请求""" property_name: Optional[str] = Field(None, description="属性名称(支持模糊搜索)") property_type: Optional[ExtendedPropertyTypeEnum] = Field(None, description="属性类型") category: Optional[str] = Field(None, description="属性分类") is_enabled: Optional[bool] = Field(None, description="是否启用") page: int = Field(1, ge=1, description="页码") page_size: int = Field(20, ge=1, le=100, description="每页数量") class ExtendedPropertyListResponse(BaseModel): """扩展属性列表响应""" total: int = Field(..., description="总数量") page: int = Field(..., description="当前页码") page_size: int = Field(..., description="每页数量") total_pages: int = Field(..., description="总页数") properties: List[ExtendedPropertyInfo] = Field(..., description="扩展属性列表") class ExtendedPropertyDeleteResponse(BaseModel): """扩展属性删除响应""" property_id: str = Field(..., description="删除的属性ID") property_name: str = Field(..., description="属性名称(唯一标识)") message: str = Field(..., description="删除结果消息") # 库位详情相关模型 class StorageLocationDetailResponse(BaseModel): """库位详情响应""" storage_location: StorageLocationInfo = Field(..., description="库位详细信息") operate_point_info: Optional[Dict[str, Any]] = Field(None, description="动作点详细信息") extended_fields_definitions: Optional[List[ExtendedPropertyInfo]] = Field(None, description="扩展字段定义") status_history: Optional[List[Dict[str, Any]]] = Field(None, description="状态变更历史") # 库位编辑相关模型 class StorageLocationEditRequest(BaseModel): """库位编辑请求""" goods_content: Optional[str] = Field(None, description="货物内容", max_length=500) goods_weight: Optional[int] = Field(None, description="货物重量(克)", ge=0) goods_volume: Optional[int] = Field(None, description="货物体积(立方厘米)", ge=0) max_weight: Optional[int] = Field(None, description="最大承重(克)", ge=0) max_volume: Optional[int] = Field(None, description="最大体积(立方厘米)", ge=0) layer_height: Optional[int] = Field(None, description="层高(毫米)", ge=0) is_locked: Optional[bool] = Field(None, description="是否锁定") is_disabled: Optional[bool] = Field(None, description="是否禁用") is_empty_tray: Optional[bool] = Field(None, description="是否空托盘") tags: Optional[str] = Field(None, description="标签", max_length=500) description: Optional[str] = Field(None, description="库位描述", max_length=1000) extended_fields: Optional[Dict[str, Any]] = Field(None, description="扩展字段值") class StorageLocationEditResponse(BaseModel): """库位编辑响应""" layer_name: str = Field(..., description="库位名称") success: bool = Field(..., description="编辑是否成功") message: str = Field(..., description="操作结果消息") updated_fields: List[str] = Field(..., description="已更新的字段列表") updated_storage_location: StorageLocationInfo = Field(..., description="更新后的库位信息") # 库位操作记录相关模型 class StorageLocationLogInfo(BaseModel): """库位操作记录信息""" id: str = Field(..., description="记录ID") operation_time: datetime = Field(..., description="操作时间") operator: str = Field(..., description="操作人") operation_type: str = Field(..., description="操作类型") affected_storage_locations: List[str] = Field(..., description="影响的库位ID列表") description: Optional[str] = Field(None, description="操作描述") created_at: datetime = Field(..., description="创建时间") class StorageLocationLogListRequest(BaseModel): """库位操作记录查询请求""" storage_location_id: Optional[str] = Field(None, description="库位ID") operator: Optional[str] = Field(None, description="操作人(支持模糊搜索)") operation_type: Optional[str] = Field(None, description="操作类型") start_time: Optional[datetime] = Field(None, description="开始时间") end_time: Optional[datetime] = Field(None, description="结束时间") page: int = Field(1, ge=1, description="页码") page_size: int = Field(20, ge=1, le=100, description="每页数量") class StorageLocationLogListResponse(BaseModel): """库位操作记录查询响应""" total: int = Field(..., description="总数量") page: int = Field(..., description="当前页码") page_size: int = Field(..., description="每页数量") total_pages: int = Field(..., description="总页数") logs: List[StorageLocationLogInfo] = Field(..., description="操作记录列表")