VWED_server/data/models/operate_point_layer.py

178 lines
6.4 KiB
Python
Raw Normal View History

2025-07-14 10:29:37 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
库区分层数据模型
管理每个动作点的分层信息和货物状态
"""
from sqlalchemy import Column, String, Integer, Boolean, Text, DateTime, ForeignKey, UniqueConstraint
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.mysql import CHAR
from .base import BaseModel
import datetime
class OperatePointLayer(BaseModel):
"""
库区分层数据模型
每个动作点可以有多个层每层可以独立存放货物
"""
__tablename__ = 'vwed_operate_point_layer'
id = Column(CHAR(64), primary_key=True, comment='层ID')
operate_point_id = Column(CHAR(64), ForeignKey('vwed_operate_point.id'), nullable=False, comment='动作点ID')
station_name = Column(String(64), nullable=False, comment='动作点名称')
2025-07-17 15:47:56 +08:00
# storage_location_name = Column(String(64), nullable=False, comment='库位名称')
2025-07-14 10:29:37 +08:00
area_name = Column(String(64), nullable=True, comment='库区名称')
scene_id = Column(String(64), nullable=False, comment='场景ID冗余字段')
layer_index = Column(Integer, nullable=False, comment='层索引(从1开始)')
2025-07-17 15:47:56 +08:00
layer_name = Column(String(64), comment='库位名称')
2025-07-14 10:29:37 +08:00
# 货物状态
is_occupied = Column(Boolean, nullable=False, default=False, comment='是否占用')
goods_content = Column(String(100), nullable=False, default='', comment='货物内容')
goods_weight = Column(Integer, comment='货物重量(克)')
goods_volume = Column(Integer, 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='是否空托盘')
locked_by = Column(String(128), nullable=True, comment='锁定者')
tags = Column(String(100), nullable=False, default='', comment='标签')
# 层属性
max_weight = Column(Integer, comment='最大承重(克)')
max_volume = Column(Integer, comment='最大体积(立方厘米)')
layer_height = Column(Integer, comment='层高(毫米)')
# 时间信息
goods_stored_at = Column(DateTime, comment='货物存放时间')
goods_retrieved_at = Column(DateTime, comment='货物取出时间')
last_access_at = Column(DateTime, comment='最后访问时间')
# 扩展信息
tags = Column(String(255), comment='层标签', nullable=True)
description = Column(Text, comment='层描述', nullable=True)
config_json = Column(Text, comment='层配置JSON', nullable=True)
# 关联关系
operate_point = relationship("OperatePoint", back_populates="layers")
# 唯一约束:同一个动作点的层索引不能重复
__table_args__ = (
UniqueConstraint('operate_point_id', 'layer_index', name='uk_operate_point_layer'),
)
def __repr__(self):
2025-07-17 15:47:56 +08:00
return f"<OperatePointLayer(id={self.id}, operate_point_id={self.operate_point_id}, station_name={self.station_name}, area_name={self.area_name}, scene_id={self.scene_id}, layer_index={self.layer_index})>"
2025-07-14 10:29:37 +08:00
def can_store_goods(self, weight=None, volume=None):
"""
检查是否可以存放货物
Args:
weight: 货物重量()
volume: 货物体积(立方厘米)
Returns:
bool: 是否可以存放
"""
if self.is_disabled or self.is_locked or self.is_occupied:
return False
# 检查重量限制
if weight is not None and self.max_weight is not None:
if weight > self.max_weight:
return False
# 检查体积限制
if volume is not None and self.max_volume is not None:
if volume > self.max_volume:
return False
return True
def can_retrieve_goods(self):
"""检查是否可以取货"""
return (not self.is_disabled and
not self.is_locked and
self.is_occupied)
def store_goods(self, content, weight=None, volume=None):
"""
存放货物
Args:
content: 货物内容
weight: 货物重量()
volume: 货物体积(立方厘米)
Returns:
bool: 是否成功
"""
if not self.can_store_goods(weight, volume):
return False
self.is_occupied = True
self.goods_content = content
self.goods_weight = weight
self.goods_volume = volume
self.goods_stored_at = datetime.datetime.now()
self.last_access_at = datetime.datetime.now()
return True
def retrieve_goods(self):
"""
取出货物
Returns:
dict: 货物信息
"""
if not self.can_retrieve_goods():
return None
goods_info = {
'content': self.goods_content,
'weight': self.goods_weight,
'volume': self.goods_volume,
'stored_at': self.goods_stored_at
}
# 清空货物信息
self.is_occupied = False
self.goods_content = ''
self.goods_weight = None
self.goods_volume = None
self.goods_retrieved_at = datetime.datetime.now()
self.last_access_at = datetime.datetime.now()
return goods_info
def get_remaining_capacity(self):
"""获取剩余容量信息"""
result = {}
if self.max_weight is not None:
used_weight = self.goods_weight if self.goods_weight is not None else 0
result['remaining_weight'] = self.max_weight - used_weight
if self.max_volume is not None:
used_volume = self.goods_volume if self.goods_volume is not None else 0
result['remaining_volume'] = self.max_volume - used_volume
return result
def is_overweight(self):
"""检查是否超重"""
if self.max_weight is None or self.goods_weight is None:
return False
return self.goods_weight > self.max_weight
def is_overflow(self):
"""检查是否超体积"""
if self.max_volume is None or self.goods_volume is None:
return False
return self.goods_volume > self.max_volume