models.py 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. from django.db import models
  2. from container.models import ContainerListModel,ContainerWCSModel,TaskModel
  3. # 库位主表(记录实时状态)
  4. class LocationModel(models.Model):
  5. LOCATION_TYPES = (
  6. ('T5', '5货位'), # 5托盘/批次
  7. ('T4', '4货位'), # 4托盘/批次
  8. ('S4', '4单货位'), # 4单托盘
  9. ('T2', '2货位'), # 2托盘/批次
  10. ('T1', '散货位'), # 1托盘
  11. ('M1', '通道区'), # 通道区
  12. ('E1', '提升机'), # 提升机
  13. ('C1', '输送机'), # 输送机
  14. ('B1', '充电桩'), # 货架区
  15. )
  16. LOCATION_STATUS = (
  17. ('available', '可用'),
  18. ('occupied', '占用'),
  19. ('disabled', '禁用'),
  20. ('reserved', '预留'),
  21. ('maintenance', '维护中'),
  22. )
  23. warehouse_code = models.CharField(max_length=255, verbose_name="Warehouse code")
  24. warehouse_name = models.CharField(max_length=255, verbose_name="Warehouse Name")
  25. shelf_type = models.CharField(max_length=255,default = 'storage', verbose_name="Shelf Type")
  26. row = models.IntegerField(verbose_name="Row") # 位置的行号
  27. col = models.IntegerField(verbose_name="Column") # 位置的列号
  28. layer = models.IntegerField(verbose_name="Layer") # 位置的层号
  29. update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
  30. empty_label = models.BooleanField(default=True, verbose_name="Empty Flag")
  31. location_code = models.CharField(max_length=20, unique=True, verbose_name='库位编码')
  32. location_group = models.CharField(max_length=20, verbose_name='库位组')
  33. # 示例:T1-L1C001-1
  34. # T1-L1C001-1 代表货位类型为T1,层号为1,列号为001,货位号为1
  35. location_type = models.CharField(max_length=3, choices=LOCATION_TYPES, verbose_name='货位类型')
  36. status = models.CharField(max_length=20, choices=LOCATION_STATUS, default='available', verbose_name='库位状态')
  37. max_capacity = models.PositiveIntegerField(verbose_name='最大容量') # 根据类型自动设置
  38. current_quantity = models.PositiveIntegerField(default=0, verbose_name='当前数')
  39. c_number = models.IntegerField(default=1, verbose_name='库位远近排序')
  40. current_containers = models.ManyToManyField(ContainerListModel,
  41. through='LocationContainerLink',
  42. verbose_name='当前存放托盘')
  43. coordinate = models.CharField(max_length=50, verbose_name='三维坐标') # 格式:行-列-层
  44. access_priority = models.IntegerField(
  45. default=0,
  46. verbose_name='访问优先级',
  47. help_text='值越大表示越远离主通道,应优先使用'
  48. )
  49. is_active = models.BooleanField(default=True, verbose_name='是否有效')
  50. class Meta:
  51. db_table = 'location'
  52. verbose_name = 'Location'
  53. verbose_name_plural = "Location"
  54. ordering = ['-id']
  55. unique_together = ( 'warehouse_code','row', 'col', 'layer') # 防止重复坐标
  56. @classmethod
  57. def get_existing_positions(cls, warehouse_code, rows, cols, layers):
  58. """获取已存在的坐标集合"""
  59. return set(
  60. cls.objects.filter(
  61. warehouse_code=warehouse_code,
  62. row__lte=rows,
  63. col__lte=cols,
  64. layer__lte=layers
  65. ).values_list('row', 'col', 'layer')
  66. )
  67. # 在LocationModel类中新增方法
  68. @classmethod
  69. def generate_locations(cls, warehouse_code):
  70. # 清空现有数据(新增部分)
  71. cls.objects.filter(warehouse_code=warehouse_code).delete()
  72. """根据规划图生成库位"""
  73. # 定义核心参数(根据规划图调整)
  74. MAIN_AISLES = [18, 1] # 子通道列号
  75. SUB_AISLES = [2,8, 13] # 主通道行号
  76. for row in range(1, 14): # 1-13行
  77. for col in range(1, 3): # 1-19列
  78. for layer in range(1, 4): # 1-3层
  79. # 判断通道区
  80. if col in MAIN_AISLES or row in SUB_AISLES:
  81. loc_type = 'M1'
  82. c_number = row
  83. # 通道
  84. if col ==1 and row == 1:
  85. loc_type = 'T1'
  86. c_number = 1
  87. # 判断货位类型(根据实际规划)
  88. else:
  89. if row <2:
  90. loc_type = 'T1'
  91. c_number = 1
  92. elif row < 8:
  93. loc_type = 'T5'
  94. c_number = row-2
  95. elif row < 13:
  96. loc_type = 'T4'
  97. c_number = row-8
  98. else:
  99. loc_type = 'T2'
  100. c_number = 16-row
  101. # 生成唯一编码
  102. location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
  103. location_group = f"{loc_type}-L{layer}C{col:03d}"
  104. # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
  105. # 创建库位
  106. cls.objects.update_or_create(
  107. warehouse_code=warehouse_code,
  108. row=row,
  109. col=col,
  110. layer=layer,
  111. c_number=c_number,
  112. shelf_type=loc_type,
  113. defaults={
  114. 'location_code': location_code,
  115. 'location_group': location_group,
  116. 'location_type': loc_type,
  117. 'max_capacity': {
  118. 'T5': 5,
  119. 'T4': 4,
  120. 'T2': 2,
  121. 'T1': 1,
  122. 'M1': 0,
  123. 'E1': 0,
  124. 'C1': 0
  125. }[loc_type],
  126. 'coordinate': f"{row}-{col}-{layer}",
  127. 'is_active': True
  128. },
  129. access_priority=c_number
  130. )
  131. for row in range(1, 16): # 1-15行
  132. for col in range(3, 17): # 1-16列
  133. for layer in range(1, 4): # 1-3层
  134. # 判断通道区
  135. if col in MAIN_AISLES or row in SUB_AISLES:
  136. loc_type = 'M1'
  137. c_number = row
  138. # 通道
  139. if col ==18 and row == 1:
  140. loc_type = 'T1'
  141. c_number = 1
  142. # 判断货位类型(根据实际规划)
  143. else:
  144. if row <2:
  145. loc_type = 'T1'
  146. c_number = 1
  147. elif row < 8:
  148. loc_type = 'T5'
  149. c_number = row-2
  150. elif row < 13:
  151. loc_type = 'T4'
  152. c_number = row-8
  153. else:
  154. loc_type = 'T2'
  155. c_number = 16-row
  156. # 生成唯一编码
  157. location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
  158. location_group = f"{loc_type}-L{layer}C{col:03d}"
  159. # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
  160. # 创建库位
  161. cls.objects.update_or_create(
  162. warehouse_code=warehouse_code,
  163. row=row,
  164. col=col,
  165. layer=layer,
  166. c_number=c_number,
  167. shelf_type=loc_type,
  168. defaults={
  169. 'location_code': location_code,
  170. 'location_group': location_group,
  171. 'location_type': loc_type,
  172. 'max_capacity': {
  173. 'T5': 5,
  174. 'T4': 4,
  175. 'T2': 2,
  176. 'T1': 1,
  177. 'M1': 0,
  178. 'E1': 0,
  179. 'C1': 0
  180. }[loc_type],
  181. 'coordinate': f"{row}-{col}-{layer}",
  182. 'is_active': True
  183. },
  184. access_priority=c_number
  185. )
  186. # print("✅ 库位生成成功!")
  187. for row in range(1, 14): # 1-15行
  188. for col in range(17, 20): # 1-16列
  189. for layer in range(1, 4): # 1-3层
  190. # 判断通道区
  191. if col in MAIN_AISLES or row in SUB_AISLES:
  192. loc_type = 'M1'
  193. c_number = row
  194. # 通道
  195. if col ==18 and row == 1:
  196. loc_type = 'T1'
  197. c_number = 1
  198. # 判断货位类型(根据实际规划)
  199. else:
  200. if row <2:
  201. loc_type = 'T1'
  202. c_number = 1
  203. elif row < 8:
  204. loc_type = 'T5'
  205. c_number = row-2
  206. elif row < 13:
  207. loc_type = 'T4'
  208. c_number = row-8
  209. else:
  210. loc_type = 'T2'
  211. c_number = 16-row
  212. # 生成唯一编码
  213. location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
  214. location_group = f"{loc_type}-L{layer}C{col:03d}"
  215. # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
  216. # 创建库位
  217. cls.objects.update_or_create(
  218. warehouse_code=warehouse_code,
  219. row=row,
  220. col=col,
  221. layer=layer,
  222. c_number=c_number,
  223. shelf_type=loc_type,
  224. defaults={
  225. 'location_code': location_code,
  226. 'location_group': location_group,
  227. 'location_type': loc_type,
  228. 'max_capacity': {
  229. 'T5': 5,
  230. 'T4': 4,
  231. 'T2': 2,
  232. 'T1': 1,
  233. 'M1': 0,
  234. 'E1': 0,
  235. 'C1': 0
  236. }[loc_type],
  237. 'coordinate': f"{row}-{col}-{layer}",
  238. 'is_active': True
  239. },
  240. access_priority=c_number
  241. )
  242. # print("✅ 库位生成成功!")
  243. for row in range(1, 18): # 1-17行
  244. for col in range(20, 30): # 19-29列
  245. for layer in range(1, 4): # 1-3层
  246. # 判断通道区
  247. if col in MAIN_AISLES or row in SUB_AISLES:
  248. loc_type = 'M1'
  249. c_number = row
  250. # 通道
  251. if col ==18 and row == 1:
  252. loc_type = 'T1'
  253. c_number = 1
  254. if col ==29 and row == 1:
  255. loc_type = 'T1'
  256. c_number = 1
  257. if col ==29 and row == 14:
  258. loc_type = 'S4'
  259. c_number = 4
  260. if col ==29 and row == 15:
  261. loc_type = 'S4'
  262. c_number = 3
  263. if col ==29 and row == 16:
  264. loc_type = 'S4'
  265. c_number = 2
  266. if col ==29 and row == 17:
  267. loc_type = 'S4'
  268. c_number = 1
  269. # 判断货位类型(根据实际规划)
  270. else:
  271. # 判断货位类型(根据实际规划)
  272. if row < 2:
  273. loc_type = 'T1'
  274. c_number = row
  275. elif row < 8:
  276. loc_type = 'T5'
  277. c_number = row-2
  278. elif row < 13:
  279. loc_type = 'T4'
  280. c_number = row-8
  281. else:
  282. loc_type = 'S4'
  283. c_number = 18-row
  284. # 生成唯一编码
  285. location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
  286. location_group = f"{loc_type}-L{layer}C{col:03d}"
  287. # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
  288. # 创建库位
  289. cls.objects.update_or_create(
  290. warehouse_code=warehouse_code,
  291. row=row,
  292. col=col,
  293. layer=layer,
  294. c_number=c_number,
  295. shelf_type=loc_type,
  296. defaults={
  297. 'location_code': location_code,
  298. 'location_group': location_group,
  299. 'location_type': loc_type,
  300. 'max_capacity': {
  301. 'T5': 5,
  302. 'T4': 4,
  303. 'S4': 4,
  304. 'T2': 2,
  305. 'T1': 1,
  306. 'M1': 0,
  307. 'E1': 0,
  308. 'C1': 0,
  309. 'B1': 0
  310. }[loc_type],
  311. 'coordinate': f"{row}-{col}-{layer}",
  312. 'is_active': True
  313. },
  314. access_priority=c_number
  315. )
  316. # 输送机
  317. for row in [14]: # 1-17行
  318. for col in [1,18]: # 1-19列
  319. for layer in range(1, 4): # 1-3层
  320. # 判断货位类型(根据实际规划)
  321. loc_type = 'C1'
  322. c_number = 1
  323. location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
  324. location_group = f"{loc_type}-L{layer}C{col:03d}"
  325. # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
  326. # 创建库位
  327. # 创建库位
  328. cls.objects.update_or_create(
  329. warehouse_code=warehouse_code,
  330. row=row,
  331. col=col,
  332. layer=layer,
  333. c_number=c_number,
  334. shelf_type=loc_type,
  335. defaults={
  336. 'location_code': location_code,
  337. 'location_group': location_group,
  338. 'location_type': loc_type,
  339. 'max_capacity': {
  340. 'T5': 5,
  341. 'T4': 4,
  342. 'S4': 4,
  343. 'T2': 2,
  344. 'T1': 1,
  345. 'M1': 0,
  346. 'E1': 0,
  347. 'C1': 0,
  348. 'B1': 0
  349. }[loc_type],
  350. 'coordinate': f"{row}-{col}-{layer}",
  351. 'is_active': True
  352. },
  353. access_priority=c_number
  354. )
  355. for row in [16]: # 1-17行
  356. for col in [1,18]: # 1-19列
  357. for layer in [1]: # 1-3层
  358. # 判断货位类型(根据实际规划)
  359. loc_type = 'C1'
  360. c_number = row
  361. location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
  362. location_group = f"{loc_type}-L{layer}C{col:03d}"
  363. # 创建库位
  364. cls.objects.update_or_create(
  365. warehouse_code=warehouse_code,
  366. row=row,
  367. col=col,
  368. layer=layer,
  369. c_number=c_number,
  370. shelf_type=loc_type,
  371. defaults={
  372. 'location_code': location_code,
  373. 'location_group': location_group,
  374. 'location_type': loc_type,
  375. 'max_capacity': {
  376. 'T5': 5,
  377. 'T4': 4,
  378. 'S4': 4,
  379. 'T2': 2,
  380. 'T1': 1,
  381. 'M1': 0,
  382. 'E1': 0,
  383. 'C1': 0,
  384. 'B1': 0
  385. }[loc_type],
  386. 'coordinate': f"{row}-{col}-{layer}",
  387. 'is_active': True
  388. },
  389. access_priority=c_number
  390. )
  391. # 提升机
  392. for row in [15]: # 1-17行
  393. for col in [1,18]: # 1-19列
  394. for layer in range(1, 4): # 1-3层
  395. # 判断货位类型(根据实际规划)
  396. loc_type = 'E1'
  397. c_number = row
  398. location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
  399. location_group = f"{loc_type}-L{layer}C{col:03d}"
  400. # 创建库位
  401. cls.objects.update_or_create(
  402. warehouse_code=warehouse_code,
  403. row=row,
  404. col=col,
  405. layer=layer,
  406. c_number=c_number,
  407. shelf_type=loc_type,
  408. defaults={
  409. 'location_code': location_code,
  410. 'location_group': location_group,
  411. 'location_type': loc_type,
  412. 'max_capacity': {
  413. 'T5': 5,
  414. 'T4': 4,
  415. 'S4': 4,
  416. 'T2': 2,
  417. 'T1': 1,
  418. 'M1': 0,
  419. 'E1': 0,
  420. 'C1': 0,
  421. 'B1': 0
  422. }[loc_type],
  423. 'coordinate': f"{row}-{col}-{layer}",
  424. 'is_active': True
  425. },
  426. access_priority=c_number
  427. )
  428. # 充电桩
  429. for row in [14]: # 1-17行
  430. for col in [2]: # 1-19列
  431. for layer in range(1, 3): # 1-3层
  432. # 判断货位类型(根据实际规划)
  433. loc_type = 'B1'
  434. c_number = 1
  435. location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
  436. location_group = f"{loc_type}-L{layer}C{col:03d}"
  437. # 创建库位
  438. cls.objects.update_or_create(
  439. warehouse_code=warehouse_code,
  440. row=row,
  441. col=col,
  442. layer=layer,
  443. c_number=c_number,
  444. shelf_type=loc_type,
  445. defaults={
  446. 'location_code': location_code,
  447. 'location_group': location_group,
  448. 'location_type': loc_type,
  449. 'max_capacity': {
  450. 'T5': 5,
  451. 'T4': 4,
  452. 'S4': 4,
  453. 'T2': 2,
  454. 'T1': 1,
  455. 'M1': 0,
  456. 'E1': 0,
  457. 'C1': 0,
  458. 'B1': 0
  459. }[loc_type],
  460. 'coordinate': f"{row}-{col}-{layer}",
  461. 'is_active': True
  462. },
  463. access_priority=c_number
  464. )
  465. class LocationGroupModel(models.Model):
  466. LOCATION_TYPES = (
  467. ('T5', '5货位'), # 5托盘/批次
  468. ('T4', '4货位'), # 4托盘/批次
  469. ('S4', '4单货位'), # 4单托盘
  470. ('T2', '2货位'), # 2托盘/批次
  471. ('T1', '散货位'), # 1托盘
  472. )
  473. LOCATION_STATUS = (
  474. ('available', '可用'),
  475. ('occupied', '占用'),
  476. ('full', '满'),
  477. ('disabled', '禁用'),
  478. ('reserved', '预留'),
  479. ('maintenance', '维护中'),
  480. )
  481. warehouse_code = models.CharField(max_length=50, verbose_name='仓库编码')
  482. group_name = models.CharField(max_length=50, verbose_name='库位组名称')
  483. group_type = models.CharField(max_length=50, choices=LOCATION_TYPES, verbose_name='库位组类型')
  484. group_code = models.CharField(max_length=50, verbose_name='库位组编码')
  485. layer = models.PositiveIntegerField(verbose_name='层数')
  486. location_items = models.ManyToManyField(LocationModel, verbose_name='库位')
  487. status = models.CharField(max_length=20, choices=LOCATION_STATUS, default='available', verbose_name='库位状态')
  488. max_capacity = models.PositiveIntegerField(verbose_name='最大容量') # 根据类型自动设置
  489. current_quantity = models.PositiveIntegerField(default=0, verbose_name='当前托盘数')
  490. current_goods_quantity = models.PositiveIntegerField(default=0, verbose_name='当前货物数')
  491. current_batch = models.CharField(max_length=50, default='', verbose_name='当前批次')
  492. current_goods_code = models.CharField(max_length=50, default='', verbose_name='当前货物编码')
  493. access_priority = models.IntegerField(
  494. default=0,
  495. verbose_name='访问优先级',
  496. help_text='值越大表示越远离主通道,应优先使用'
  497. )
  498. left_priority = models.IntegerField(
  499. default=0,
  500. verbose_name='左侧优先级',
  501. help_text='值越大表示越靠左,应优先使用'
  502. )
  503. right_priority = models.IntegerField(
  504. default=0,
  505. verbose_name='右侧优先级',
  506. help_text='值越大表示越靠右,应优先使用'
  507. )
  508. is_active = models.BooleanField(default=True, verbose_name='是否有效')
  509. # create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
  510. class Meta:
  511. db_table = 'location_group'
  512. verbose_name = 'Location Group'
  513. verbose_name_plural = "Location Group"
  514. ordering = ['-id']
  515. unique_together = ( 'warehouse_code', 'group_code') # 防止重复组编码
  516. @classmethod
  517. def generate_group(cls,warehouse_code):
  518. cls.objects.filter(warehouse_code=warehouse_code).delete()
  519. MAIN_AISLES = [18, 1] # 子通道列号
  520. SUB_AISLES = [2,8, 13] # 主通道行号
  521. for row in range(1, 14): # 1-13行
  522. for col in range(1, 3): # 1-19列
  523. for layer in range(1, 4): # 1-3层
  524. # 判断通道区
  525. if col in MAIN_AISLES or row in SUB_AISLES:
  526. loc_type = 'M1'
  527. c_number = row
  528. # 通道
  529. if col ==1 and row == 1:
  530. loc_type = 'T1'
  531. c_number = 1
  532. # 判断货位类型(根据实际规划)
  533. else:
  534. if row <2:
  535. loc_type = 'T1'
  536. c_number = 1
  537. elif row < 8:
  538. loc_type = 'T5'
  539. c_number = row-2
  540. elif row < 13:
  541. loc_type = 'T4'
  542. c_number = row-8
  543. else:
  544. loc_type = 'T2'
  545. c_number = 16-row
  546. # 生成唯一编码
  547. print(f"生成库组:{row}-{col}-{layer}")
  548. if loc_type == 'M1':
  549. continue
  550. # 创建库位
  551. group_code = f"{loc_type}-L{layer}C{col:03d}"
  552. group_name = f"{loc_type}-L{layer}C{col:03d}"
  553. # 使用(row+col)*layer作为库位排序
  554. left_priority = (abs(row-13)+abs(col-1))*layer
  555. right_priority = (abs(row-13)+abs(col-18))*layer
  556. if cls.objects.filter(warehouse_code=warehouse_code, group_code=group_code).exists():
  557. group_item = cls.objects.get(warehouse_code=warehouse_code, group_code=group_code)
  558. group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
  559. group_item.save()
  560. else:
  561. group_item = cls.objects.create(
  562. warehouse_code=warehouse_code,
  563. layer=layer,
  564. group_name=group_name,
  565. group_type=loc_type,
  566. group_code=group_code,
  567. max_capacity={
  568. 'T5': 5,
  569. 'T4': 4,
  570. 'T2': 2,
  571. 'T1': 1,
  572. 'S4': 4,
  573. 'M1': 0,
  574. 'E1': 0,
  575. 'C1': 0
  576. }[loc_type],
  577. current_quantity=0,
  578. status='available',
  579. access_priority=c_number,
  580. left_priority=left_priority,
  581. right_priority=right_priority,
  582. is_active=True
  583. )
  584. group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
  585. group_item.save()
  586. for row in range(1, 16): # 1-15行
  587. for col in range(3, 17): # 1-16列
  588. for layer in range(1, 4): # 1-3层
  589. # 判断通道区
  590. if col in MAIN_AISLES or row in SUB_AISLES:
  591. loc_type = 'M1'
  592. c_number = row
  593. # 通道
  594. if col ==18 and row == 1:
  595. loc_type = 'T1'
  596. c_number = 1
  597. # 判断货位类型(根据实际规划)
  598. else:
  599. if row <2:
  600. loc_type = 'T1'
  601. c_number = 1
  602. elif row < 8:
  603. loc_type = 'T5'
  604. c_number = row-2
  605. elif row < 13:
  606. loc_type = 'T4'
  607. c_number = row-8
  608. else:
  609. loc_type = 'T2'
  610. c_number = 16-row
  611. # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
  612. if loc_type == 'M1':
  613. continue
  614. # 创建库位
  615. group_code = f"{loc_type}-L{layer}C{col:03d}"
  616. group_name = f"{loc_type}-L{layer}C{col:03d}"
  617. left_priority = (abs(row-13)+abs(col-1))*layer
  618. right_priority = (abs(row-13)+abs(col-18))*layer
  619. if cls.objects.filter(warehouse_code=warehouse_code, group_code=group_code).exists():
  620. group_item = cls.objects.get(warehouse_code=warehouse_code, group_code=group_code)
  621. group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
  622. group_item.save()
  623. else:
  624. group_item = cls.objects.create(
  625. warehouse_code=warehouse_code,
  626. layer=layer,
  627. group_name=group_name,
  628. group_type=loc_type,
  629. group_code=group_code,
  630. max_capacity={
  631. 'T5': 5,
  632. 'T4': 4,
  633. 'T2': 2,
  634. 'T1': 1,
  635. 'S4': 4,
  636. 'M1': 0,
  637. 'E1': 0,
  638. 'C1': 0
  639. }[loc_type],
  640. current_quantity=0,
  641. status='available',
  642. access_priority=c_number,
  643. left_priority=left_priority,
  644. right_priority=right_priority,
  645. is_active=True
  646. )
  647. group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
  648. group_item.save()
  649. for row in range(1, 14): # 1-15行
  650. for col in range(17, 20): # 1-16列
  651. for layer in range(1, 4): # 1-3层
  652. # 判断通道区
  653. if col in MAIN_AISLES or row in SUB_AISLES:
  654. loc_type = 'M1'
  655. c_number = row
  656. # 通道
  657. if col ==18 and row == 1:
  658. loc_type = 'T1'
  659. c_number = 1
  660. # 判断货位类型(根据实际规划)
  661. else:
  662. if row <2:
  663. loc_type = 'T1'
  664. c_number = 1
  665. elif row < 8:
  666. loc_type = 'T5'
  667. c_number = row-2
  668. elif row < 13:
  669. loc_type = 'T4'
  670. c_number = row-8
  671. else:
  672. loc_type = 'T2'
  673. c_number = 16-row
  674. # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
  675. if loc_type == 'M1':
  676. continue
  677. # 创建库位
  678. group_code = f"{loc_type}-L{layer}C{col:03d}"
  679. group_name = f"{loc_type}-L{layer}C{col:03d}"
  680. left_priority = (abs(row-13)+abs(col-1))*layer
  681. right_priority = (abs(row-13)+abs(col-18))*layer
  682. if cls.objects.filter(warehouse_code=warehouse_code, group_code=group_code).exists():
  683. group_item = cls.objects.get(warehouse_code=warehouse_code, group_code=group_code)
  684. group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
  685. group_item.save()
  686. else:
  687. group_item = cls.objects.create(
  688. warehouse_code=warehouse_code,
  689. layer=layer,
  690. group_name=group_name,
  691. group_type=loc_type,
  692. group_code=group_code,
  693. max_capacity={
  694. 'T5': 5,
  695. 'T4': 4,
  696. 'T2': 2,
  697. 'T1': 1,
  698. 'S4': 4,
  699. 'M1': 0,
  700. 'E1': 0,
  701. 'C1': 0
  702. }[loc_type],
  703. current_quantity=0,
  704. status='available',
  705. access_priority=c_number,
  706. left_priority=left_priority,
  707. right_priority=right_priority,
  708. is_active=True
  709. )
  710. group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
  711. group_item.save()
  712. for row in range(1, 18): # 1-17行
  713. for col in range(20, 30): # 19-29列
  714. for layer in range(1, 4): # 1-3层
  715. # 判断通道区
  716. if col in MAIN_AISLES or row in SUB_AISLES:
  717. loc_type = 'M1'
  718. c_number = row
  719. # 通道
  720. if col ==18 and row == 1:
  721. loc_type = 'T1'
  722. c_number = 1
  723. if col ==29 and row == 1:
  724. loc_type = 'T1'
  725. c_number = 1
  726. if col ==29 and row == 14:
  727. loc_type = 'S4'
  728. c_number = 4
  729. if col ==29 and row == 15:
  730. loc_type = 'S4'
  731. c_number = 3
  732. if col ==29 and row == 16:
  733. loc_type = 'S4'
  734. c_number = 2
  735. if col ==29 and row == 17:
  736. loc_type = 'S4'
  737. c_number = 1
  738. # 判断货位类型(根据实际规划)
  739. else:
  740. # 判断货位类型(根据实际规划)
  741. if row < 2:
  742. loc_type = 'T1'
  743. c_number = row
  744. elif row < 8:
  745. loc_type = 'T5'
  746. c_number = row-2
  747. elif row < 13:
  748. loc_type = 'T4'
  749. c_number = row-8
  750. else:
  751. loc_type = 'S4'
  752. c_number = 18-row
  753. # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
  754. if loc_type == 'M1':
  755. continue
  756. # 创建库位
  757. group_code = f"{loc_type}-L{layer}C{col:03d}"
  758. group_name = f"{loc_type}-L{layer}C{col:03d}"
  759. left_priority = (abs(row-13)+abs(col-1))*layer
  760. right_priority = (abs(row-13)+abs(col-18))*layer
  761. if cls.objects.filter(warehouse_code=warehouse_code, group_code=group_code).exists():
  762. group_item = cls.objects.get(warehouse_code=warehouse_code, group_code=group_code)
  763. group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
  764. group_item.save()
  765. else:
  766. group_item = cls.objects.create(
  767. warehouse_code=warehouse_code,
  768. layer=layer,
  769. group_name=group_name,
  770. group_type=loc_type,
  771. group_code=group_code,
  772. max_capacity={
  773. 'T5': 5,
  774. 'T4': 4,
  775. 'T2': 2,
  776. 'T1': 1,
  777. 'S4': 4,
  778. 'M1': 0,
  779. 'E1': 0,
  780. 'C1': 0
  781. }[loc_type],
  782. current_quantity=0,
  783. status='available',
  784. access_priority=c_number,
  785. left_priority=left_priority,
  786. right_priority=right_priority,
  787. is_active=True
  788. )
  789. group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
  790. group_item.save()
  791. # 库位-托盘关联表(记录实时存放关系)
  792. class LocationContainerLink(models.Model):
  793. location = models.ForeignKey(LocationModel, on_delete=models.CASCADE, verbose_name='库位')
  794. container = models.ForeignKey(ContainerListModel,on_delete=models.CASCADE)
  795. task_wcs = models.ForeignKey(ContainerWCSModel, on_delete=models.CASCADE, null=True, blank=True)
  796. task_detail = models.ForeignKey(TaskModel, on_delete=models.CASCADE, null=True, blank=True)
  797. put_time = models.DateTimeField(auto_now_add=True, verbose_name='上架时间')
  798. operator = models.CharField(max_length=50, verbose_name='操作人')
  799. is_active = models.BooleanField(default=True, verbose_name='是否有效')
  800. class Meta:
  801. db_table = 'location_container_link'
  802. verbose_name = 'Location-Container Link'
  803. verbose_name_plural = "Location-Container Link"
  804. ordering = ['-id']
  805. unique_together = ( 'location', 'container') # 防止重复关联
  806. class DeviceModel(models.Model):
  807. location = models.ForeignKey(LocationModel, on_delete=models.CASCADE)
  808. device_id = models.CharField(max_length=255, verbose_name="Device ID")
  809. device_name = models.CharField(max_length=255, verbose_name="Device Name")
  810. device_type = models.CharField(max_length=255, verbose_name="Device Type")
  811. ip_address = models.CharField(max_length=255, verbose_name="IP Address")
  812. port = models.IntegerField(verbose_name="Port")
  813. status = models.CharField(max_length=255, verbose_name="Status")
  814. create_time = models.DateTimeField(auto_now_add=True, verbose_name="Create Time")
  815. update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
  816. class Meta:
  817. db_table = 'device'
  818. verbose_name = 'Device'
  819. verbose_name_plural = "Device"
  820. ordering = ['-id']
  821. unique_together = ( 'location', 'device_id') # 防止重复设备
  822. # 库位变更记录(历史追溯)
  823. class LocationChangeLog(models.Model):
  824. OPERATION_TYPES = (
  825. ('put', '上架'),
  826. ('pick', '下架'),
  827. ('move_in', '移入'),
  828. ('move_out', '移出')
  829. )
  830. location = models.ForeignKey(LocationModel, on_delete=models.CASCADE, verbose_name='库位')
  831. container = models.ForeignKey(ContainerListModel, on_delete=models.CASCADE, verbose_name='托盘')
  832. task_wcs = models.ForeignKey(ContainerWCSModel, on_delete=models.CASCADE, null=True, blank=True, verbose_name='WCS任务')
  833. task_detail = models.ForeignKey(TaskModel, on_delete=models.CASCADE, null=True, blank=True, verbose_name='批次详情')
  834. operation_type = models.CharField(max_length=10, choices=OPERATION_TYPES, verbose_name='操作类型')
  835. related_location = models.ForeignKey(LocationModel,
  836. on_delete=models.SET_NULL,
  837. null=True,
  838. related_name='related_logs',
  839. verbose_name='关联库位') # 用于移库操作
  840. timestamp = models.DateTimeField(auto_now_add=True, verbose_name='操作时间')
  841. class Meta:
  842. db_table = 'location_change_log'
  843. verbose_name = 'Location Change Log'
  844. verbose_name_plural = "Location Change Log"
  845. ordering = ['-id']
  846. class alloction_pre(models.Model):
  847. batch_number = models.CharField(max_length=255, verbose_name='批次号')
  848. layer_pre_type = models.JSONField(default=list, verbose_name='预留方案')
  849. layer1_pressure = models.IntegerField(default=0, verbose_name='第一层工作压力')
  850. layer2_pressure = models.IntegerField(default=0, verbose_name='第二层工作压力')
  851. layer3_pressure = models.IntegerField(default=0, verbose_name='第三层工作压力')
  852. create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
  853. class Meta:
  854. db_table = 'allocation_pre'
  855. verbose_name = 'Allocation_pre'
  856. verbose_name_plural = "Allocation_pre"
  857. ordering = ['-id']
  858. class allocation_history(models.Model):
  859. location = models.ForeignKey(LocationModel, on_delete=models.CASCADE, verbose_name='库位')
  860. container = models.ForeignKey(ContainerListModel, on_delete=models.CASCADE, verbose_name='托盘')
  861. task_wcs = models.ForeignKey(ContainerWCSModel, on_delete=models.CASCADE, null=True, blank=True, verbose_name='WCS任务')
  862. task_detail = models.ForeignKey(TaskModel, on_delete=models.CASCADE, null=True, blank=True, verbose_name='批次详情')
  863. operation_type = models.CharField(max_length=10, verbose_name='操作类型')
  864. related_location = models.ForeignKey(LocationModel,
  865. on_delete=models.SET_NULL,
  866. null=True,
  867. related_name='related_logs_history',
  868. verbose_name='关联库位') # 用于移库操作
  869. timestamp = models.DateTimeField(auto_now_add=True, verbose_name='操作时间')
  870. class Meta:
  871. db_table = 'allocation_history'
  872. verbose_name = 'Allocation_history'
  873. verbose_name_plural = "Allocation_history"
  874. ordering = ['-id']