VWED_server/data/models/operate_point_layer.py
2025-07-17 15:47:56 +08:00

178 lines
6.4 KiB
Python
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.

#!/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='动作点名称')
# storage_location_name = Column(String(64), nullable=False, comment='库位名称')
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开始)')
layer_name = Column(String(64), comment='库位名称')
# 货物状态
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):
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})>"
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