#!/usr/bin/env python # -*- coding: utf-8 -*- """ 动作点数据模型 基于现有的vwed_operate_point表结构进行扩展 动作点和库位是同一个概念 """ from sqlalchemy import Column, String, Integer, Boolean, Text, DateTime, ForeignKey, Enum from sqlalchemy.orm import relationship from sqlalchemy.dialects.mysql import CHAR from .base import BaseModel from .storage_area import StorageAreaType class OperatePoint(BaseModel): """ 动作点数据模型 继承现有的vwed_operate_point表结构并扩展 """ __tablename__ = 'vwed_operate_point' id = Column(CHAR(64), primary_key=True, comment='动作点ID') station_name = Column(String(64), nullable=False, comment='动作站点名称') # storage_location_name = Column(String(64), nullable=False, comment='库位名称') scene_id = Column(String(64), nullable=False, comment='场景ID') # 原有字段 # is_occupied = Column(Boolean, nullable=False, default=False, comment='是否占用') # is_locked = Column(Boolean, nullable=False, default=False, comment='是否锁定') is_disabled = Column(Boolean, nullable=False, default=False, comment='是否禁用') # is_empty_tray = Column(Boolean, nullable=False, default=False, comment='是否空托盘') content = Column(String(100), nullable=False, default='', comment='内容') tags = Column(String(100), nullable=False, default='', comment='标签') # 库区关联 storage_area_id = Column(CHAR(64), ForeignKey('vwed_storage_area.id'), nullable=True, comment='所属库区ID') # 库区类型 storage_area_type = Column(Enum(StorageAreaType), nullable=True, comment='库区类型') # 库区名称 area_name = Column(String(64), nullable=True, comment='库区名称') # 动作点属性 max_layers = Column(Integer, nullable=False, default=1, comment='最大层数') current_layers = Column(Integer, nullable=False, default=0, comment='当前使用层数') # 动作点位置信息 position_x = Column(Integer, comment='X坐标', nullable=True) position_y = Column(Integer, comment='Y坐标', nullable=True) position_z = Column(Integer, comment='Z坐标', nullable=True) # 动作点配置 description = Column(Text, comment='动作点描述') # 关联关系 storage_area = relationship("StorageArea", back_populates="operate_points") layers = relationship( "OperatePointLayer", back_populates="operate_point", cascade="all, delete-orphan", order_by="OperatePointLayer.layer_index" ) def __repr__(self): return f"" def get_available_layers(self): """获取可用层数""" return self.max_layers - self.current_layers def get_layer_usage_rate(self): """获取层使用率""" if self.max_layers == 0: return 0.0 return (self.current_layers / self.max_layers) * 100.0 def is_full(self): """是否已满""" return self.current_layers >= self.max_layers def is_empty(self): """是否为空""" return self.current_layers == 0 def can_store_goods(self): """是否可以存放货物""" return (not self.is_disabled and not self.is_full() and self.max_layers > 0) def can_retrieve_goods(self): """是否可以取货""" return (not self.is_disabled and not self.is_empty()) def get_occupied_layers(self): """获取有货物的层列表""" return [layer for layer in self.layers if layer.is_occupied] def get_empty_layers(self): """获取空层列表""" return [layer for layer in self.layers if not layer.is_occupied] def has_storage_area(self): """是否属于某个库区""" return self.storage_area_id is not None def get_storage_area_info(self): """获取库区信息""" if self.storage_area_id is None: return None return self.storage_area def is_dense_storage(self): """是否为密集库区类型""" return self.storage_area_type == StorageAreaType.DENSE def is_general_storage(self): """是否为一般库区类型""" return self.storage_area_type == StorageAreaType.GENERAL def get_storage_area_display_name(self): """获取库区显示名称""" return self.area_name or "未分配库区"