from django.db import models from container.models import ContainerListModel,ContainerWCSModel,TaskModel # 库位主表(记录实时状态) class LocationModel(models.Model): LOCATION_TYPES = ( ('T5', '5货位'), # 5托盘/批次 ('T4', '4货位'), # 4托盘/批次 ('S4', '4单货位'), # 4单托盘 ('T2', '2货位'), # 2托盘/批次 ('T1', '散货位'), # 1托盘 ('M1', '通道区'), # 通道区 ('E1', '提升机'), # 提升机 ('C1', '输送机'), # 输送机 ) LOCATION_STATUS = ( ('available', '可用'), ('occupied', '占用'), ('disabled', '禁用'), ('reserved', '预留'), ('maintenance', '维护中'), ) warehouse_code = models.CharField(max_length=255, verbose_name="Warehouse code") warehouse_name = models.CharField(max_length=255, verbose_name="Warehouse Name") shelf_type = models.CharField(max_length=255,default = 'storage', verbose_name="Shelf Type") row = models.IntegerField(verbose_name="Row") # 位置的行号 col = models.IntegerField(verbose_name="Column") # 位置的列号 layer = models.IntegerField(verbose_name="Layer") # 位置的层号 update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time") empty_label = models.BooleanField(default=True, verbose_name="Empty Flag") location_code = models.CharField(max_length=20, unique=True, verbose_name='库位编码') # 示例:T1-L1C001-1 # T1-L1C001-1 代表货位类型为T1,层号为1,列号为001,货位号为1 location_type = models.CharField(max_length=3, choices=LOCATION_TYPES, verbose_name='货位类型') status = models.CharField(max_length=20, choices=LOCATION_STATUS, default='available', verbose_name='库位状态') max_capacity = models.PositiveIntegerField(verbose_name='最大容量') # 根据类型自动设置 current_quantity = models.PositiveIntegerField(default=0, verbose_name='当前托盘数') current_containers = models.ManyToManyField(ContainerListModel, through='LocationContainerLink', verbose_name='当前存放托盘') coordinate = models.CharField(max_length=50, verbose_name='三维坐标') # 格式:行-列-层 access_priority = models.IntegerField( default=0, verbose_name='访问优先级', help_text='值越大表示越远离主通道,应优先使用' ) is_active = models.BooleanField(default=True, verbose_name='是否有效') class Meta: db_table = 'location' verbose_name = 'Location' verbose_name_plural = "Location" ordering = ['-id'] unique_together = ( 'warehouse_code','row', 'col', 'layer') # 防止重复坐标 @classmethod def get_existing_positions(cls, warehouse_code, rows, cols, layers): """获取已存在的坐标集合""" return set( cls.objects.filter( warehouse_code=warehouse_code, row__lte=rows, col__lte=cols, layer__lte=layers ).values_list('row', 'col', 'layer') ) # 在LocationModel类中新增方法 @classmethod def generate_locations(cls, warehouse_code): # 清空现有数据(新增部分) cls.objects.filter(warehouse_code=warehouse_code).delete() """根据规划图生成库位""" # 定义核心参数(根据规划图调整) MAIN_AISLES = [18, 29] # 子通道列号 SUB_AISLES = [2,8, 13] # 主通道行号 for row in range(1, 16): # 1-15行 for col in range(1, 19): # 1-19列 for layer in range(1, 4): # 1-3层 # 判断通道区 if col in MAIN_AISLES or row in SUB_AISLES: loc_type = 'M1' c_number = row if col ==18 and row == 1: loc_type = 'T1' c_number = 1 # 判断货位类型(根据实际规划) else: if row <2: loc_type = 'T1' c_number = 1 elif row < 8: loc_type = 'T5' c_number = row-2 elif row < 13: loc_type = 'T4' c_number = row-8 else: loc_type = 'T2' c_number = 16-row # 生成唯一编码 location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}" print(f"生成库位:{location_code}-{row}-{col}-{layer}") # 创建库位 cls.objects.update_or_create( warehouse_code=warehouse_code, row=row, col=col, layer=layer, defaults={ 'location_code': location_code, 'location_type': loc_type, 'max_capacity': { 'T5': 5, 'T4': 4, 'T2': 2, 'T1': 1, 'M1': 0, 'E1': 0, 'C1': 0 }[loc_type], 'coordinate': f"{row}-{col}-{layer}", 'is_active': True }, access_priority=c_number if loc_type == 'T1'or loc_type == 'T2'or loc_type == 'T4'or loc_type == 'T5' else 0 ) print("✅ 库位生成成功!") for row in range(1, 18): # 1-17行 for col in range(19, 30): # 19-29列 for layer in range(1, 4): # 1-3层 # 判断货位类型(根据实际规划) if row < 2: loc_type = 'T1' c_number = row if col ==18 and row == 1: loc_type = 'T1' c_number = 1 if col ==29 and row == 1: loc_type = 'T1' c_number = 1 elif row < 8: loc_type = 'T5' c_number = row-2 elif row < 13: loc_type = 'T4' c_number = row-8 else: loc_type = 'S4' c_number = 20-row # 生成唯一编码 location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}" # 生成唯一编码 location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}" print(f"生成库位:{location_code}-{row}-{col}-{layer}") # 创建库位 cls.objects.update_or_create( warehouse_code=warehouse_code, row=row, col=col, layer=layer, defaults={ 'location_code': location_code, 'location_type': loc_type, 'max_capacity': { 'T5': 5, 'T4': 4, 'S4': 4, 'T2': 2, 'T1': 1, 'M1': 0, 'E1': 0, 'C1': 0 }[loc_type], 'coordinate': f"{row}-{col}-{layer}", 'is_active': True }, access_priority=c_number if loc_type == 'T1'or loc_type == 'T2'or loc_type == 'T4'or loc_type == 'T5' else 0 ) # 库位-托盘关联表(记录实时存放关系) class LocationContainerLink(models.Model): location = models.ForeignKey(LocationModel, on_delete=models.CASCADE) container = models.ForeignKey(ContainerListModel, on_delete=models.CASCADE) task_wcs = models.ForeignKey(ContainerWCSModel, on_delete=models.CASCADE, null=True, blank=True) task_detail = models.ForeignKey(TaskModel, on_delete=models.CASCADE, null=True, blank=True) put_time = models.DateTimeField(auto_now_add=True, verbose_name='上架时间') operator = models.CharField(max_length=50, verbose_name='操作人') is_active = models.BooleanField(default=True, verbose_name='是否有效') class Meta: db_table = 'location_container_link' verbose_name = 'Location-Container Link' verbose_name_plural = "Location-Container Link" ordering = ['-id'] unique_together = ( 'location', 'container') # 防止重复关联关系 class DeviceModel(models.Model): location = models.ForeignKey(LocationModel, on_delete=models.CASCADE) device_id = models.CharField(max_length=255, verbose_name="Device ID") device_name = models.CharField(max_length=255, verbose_name="Device Name") device_type = models.CharField(max_length=255, verbose_name="Device Type") ip_address = models.CharField(max_length=255, verbose_name="IP Address") port = models.IntegerField(verbose_name="Port") status = models.CharField(max_length=255, verbose_name="Status") create_time = models.DateTimeField(auto_now_add=True, verbose_name="Create Time") update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time") class Meta: db_table = 'device' verbose_name = 'Device' verbose_name_plural = "Device" ordering = ['-id'] unique_together = ('device_id',) # 防止重复设备ID # 库位变更记录(历史追溯) class LocationChangeLog(models.Model): OPERATION_TYPES = ( ('put', '上架'), ('pick', '下架'), ('move_in', '移入'), ('move_out', '移出') ) location = models.ForeignKey(LocationModel, on_delete=models.CASCADE, verbose_name='库位') container = models.ForeignKey(ContainerListModel, on_delete=models.CASCADE, verbose_name='托盘') task_wcs = models.ForeignKey(ContainerWCSModel, on_delete=models.CASCADE, null=True, blank=True, verbose_name='WCS任务') task_detail = models.ForeignKey(TaskModel, on_delete=models.CASCADE, null=True, blank=True, verbose_name='批次详情') operation_type = models.CharField(max_length=10, choices=OPERATION_TYPES, verbose_name='操作类型') related_location = models.ForeignKey(LocationModel, on_delete=models.SET_NULL, null=True, related_name='related_logs', verbose_name='关联库位') # 用于移库操作 timestamp = models.DateTimeField(auto_now_add=True, verbose_name='操作时间') class Meta: db_table = 'location_change_log' verbose_name = 'Location Change Log' verbose_name_plural = "Location Change Log" ordering = ['-id']