models.py 44 KB

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