serializers.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. from rest_framework import serializers
  2. from .models import ContainerListModel,ContainerDetailModel,ContainerOperationModel,TaskModel,ContainerWCSModel,out_batch_detail,ContainerDetailLogModel,batchLogModel,DispatchConfig,WCSTaskLogModel
  3. from bound.models import BoundBatchModel,BoundDetailModel
  4. from bin.models import LocationGroupModel
  5. from utils import datasolve
  6. from decimal import Decimal
  7. class batchLogModelSerializer(serializers.ModelSerializer):
  8. # 定义批次日志的序列化器,用于获取操作,字段只读
  9. bound_code = serializers.SerializerMethodField()
  10. batch_code = serializers.CharField(source='batch.bound_number', read_only=True)
  11. goods_unit = serializers.CharField(source='batch.goods_unit', read_only=True)
  12. check_status = serializers.IntegerField(source='batch.check_status', read_only=True)
  13. create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', required=False)
  14. class Meta:
  15. # 指定模型和排除字段
  16. model = batchLogModel
  17. fields= ['id', 'bound_code', 'batch_code', 'log_type', 'goods_code', 'goods_desc', 'goods_in_qty', 'goods_out_qty', 'goods_unit','check_status','create_time']
  18. read_only_fields = ['id']
  19. def get_bound_code(self, obj):
  20. """ 动态序列化关联的批次数据 """
  21. return obj.bound.bound_code if obj.bound else '无主单,涉及手动操作'
  22. class WCSTaskGetSerializer(serializers.ModelSerializer):
  23. batch_code = serializers.CharField(source='batch.bound_number', read_only=True)
  24. outbound_code = serializers.SerializerMethodField()
  25. related_batch_number = serializers.SerializerMethodField()
  26. location_group_code = serializers.SerializerMethodField()
  27. class Meta:
  28. # 指定模型和排除字段
  29. model = ContainerWCSModel
  30. fields= '__all__'
  31. read_only_fields = ['id']
  32. def get_field_names(self, declared_fields, info):
  33. base_fields = super().get_field_names(declared_fields, info)
  34. extra = ['batch_code', 'outbound_code', 'related_batch_number', 'location_group_code']
  35. return list(dict.fromkeys(list(base_fields) + extra))
  36. def get_outbound_code(self, obj):
  37. if getattr(obj, 'bound_list_id', None) and obj.bound_list:
  38. return obj.bound_list.bound_code
  39. if getattr(obj, 'batch_out_id', None) and obj.batch_out and obj.batch_out.bound_list:
  40. return obj.batch_out.bound_list.bound_code
  41. return None
  42. def get_related_batch_number(self, obj):
  43. if getattr(obj, 'batch_out_id', None) and obj.batch_out:
  44. if obj.batch_out.batch_number:
  45. return obj.batch_out.batch_number.bound_number
  46. return obj.batch_out.out_number
  47. if getattr(obj, 'batch_id', None) and obj.batch:
  48. return obj.batch.bound_number
  49. return obj.batch_number
  50. def get_location_group_code(self, obj):
  51. if not getattr(obj, 'location_group_id', None):
  52. return None
  53. cache = getattr(self, '_location_group_cache', {})
  54. if obj.location_group_id not in cache:
  55. cache[obj.location_group_id] = LocationGroupModel.objects.filter(
  56. id=obj.location_group_id
  57. ).values_list('group_code', flat=True).first()
  58. self._location_group_cache = cache
  59. return cache.get(obj.location_group_id)
  60. class ContainerDetailLogSerializer(serializers.ModelSerializer):
  61. batch = serializers.SerializerMethodField()
  62. container_code = serializers.SerializerMethodField()
  63. goods_code = serializers.SerializerMethodField()
  64. goods_desc = serializers.SerializerMethodField()
  65. detail_goods_qty = serializers.SerializerMethodField()
  66. goods_qty = serializers.SerializerMethodField()
  67. goods_out_qty = serializers.SerializerMethodField()
  68. batch_goods_qty = serializers.SerializerMethodField() #计划入库数量
  69. batch_goods_in_qty = serializers.SerializerMethodField() #实际入库数量
  70. batch_goods_in_location_qty = serializers.SerializerMethodField() #实际在库数量
  71. batch_goods_out_qty = serializers.SerializerMethodField()
  72. create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', required=False)
  73. class Meta:
  74. # 指定模型和排除字段
  75. model = ContainerDetailLogModel
  76. fields= '__all__'
  77. read_only_fields = ['id']
  78. def get_batch(self, obj):
  79. """ 动态序列化关联的批次数据 """
  80. return obj.container_detail.batch.bound_number if obj.container_detail.batch else 'N/A'
  81. def get_container_code(self, obj):
  82. return obj.container_detail.container.container_code if obj.container_detail.container.container_code else 'N/A'
  83. def get_goods_code(self, obj):
  84. return obj.container_detail.goods_code if obj.container_detail.goods_code else 'N/A'
  85. def get_goods_desc(self, obj):
  86. return obj.container_detail.goods_desc if obj.container_detail.goods_desc else 'N/A'
  87. # 获取托盘最小单元detail的入库数量
  88. def get_detail_goods_qty(self, obj):
  89. return obj.container_detail.goods_qty if obj.container_detail.goods_qty else Decimal('0')
  90. # 获取托盘最小单元detail的 入库操作数量
  91. def get_goods_qty(self, obj):
  92. new_goods_qty = obj.new_goods_qty if obj.new_goods_qty else Decimal('0')
  93. old_goods_qty = obj.old_goods_qty if obj.old_goods_qty else Decimal('0')
  94. goods_qty = new_goods_qty - old_goods_qty
  95. return goods_qty if goods_qty else Decimal('0')
  96. # 获取托盘最小单元detail的 出库操作数量
  97. def get_goods_out_qty(self, obj):
  98. new_goods_out_qty = obj.new_goods_out_qty if obj.new_goods_out_qty else Decimal('0')
  99. old_goods_out_qty = obj.old_goods_out_qty if obj.old_goods_out_qty else Decimal('0')
  100. goods_out_qty = new_goods_out_qty - old_goods_out_qty
  101. return goods_out_qty if goods_out_qty else Decimal('0')
  102. # 获取批次的计划入库数量
  103. def get_batch_goods_qty(self, obj):
  104. return obj.container_detail.batch.goods_qty if obj.container_detail.batch.goods_qty else Decimal('0')
  105. # 获取批次的实际入库数量
  106. def get_batch_goods_in_qty(self, obj):
  107. return obj.container_detail.batch.goods_in_qty if obj.container_detail.batch.goods_in_qty else Decimal('0')
  108. # 获取批次的实际在库数量
  109. def get_batch_goods_in_location_qty(self, obj):
  110. return obj.container_detail.batch.goods_in_location_qty if obj.container_detail.batch.goods_in_location_qty else Decimal('0')
  111. # 获取批次的出库数量
  112. def get_batch_goods_out_qty(self, obj):
  113. return obj.container_detail.batch.goods_out_qty if obj.container_detail.batch.goods_out_qty else Decimal('0')
  114. class ContainerListGetSerializer(serializers.ModelSerializer):
  115. # 定义主单列表的序列化器,用于获取操作,字段只读
  116. container_code = serializers.IntegerField(read_only=True, required=False)
  117. current_location = serializers.CharField(read_only=True, required=False)
  118. target_location = serializers.CharField(read_only=True, required=False)
  119. status = serializers.IntegerField(read_only=True, required=False)
  120. last_operation = serializers.DateTimeField(read_only=True, format='%Y-%m-%d', required=False)
  121. class Meta:
  122. # 指定模型和排除字段
  123. model = ContainerListModel
  124. fields= '__all__'
  125. read_only_fields = ['id']
  126. class ContainerListPostSerializer(serializers.ModelSerializer):
  127. # 定义主单列表的序列化器,用于创建操作,允许部分字段写入
  128. container_code = serializers.IntegerField(read_only=False, required=True, validators=[datasolve.data_validate])
  129. current_location = serializers.CharField(read_only=False, required=False, validators=[datasolve.data_validate])
  130. target_location = serializers.CharField(read_only=False, required=False, validators=[datasolve.data_validate])
  131. status = serializers.IntegerField(read_only=False, required=False, validators=[datasolve.data_validate])
  132. last_operation = serializers.DateTimeField(read_only=False, format='%Y-%m-%d', required=False, validators=[datasolve.data_validate])
  133. class Meta:
  134. # 指定模型和排除字段
  135. model = ContainerListModel
  136. fields= '__all__'
  137. read_only_fields = ['id' ]
  138. class ContainerDetailSimpleGetSerializer(serializers.ModelSerializer):
  139. batch = serializers.SerializerMethodField()
  140. class Meta:
  141. # 指定模型和排除字段
  142. model = ContainerDetailModel
  143. fields= '__all__'
  144. read_only_fields = ['id']
  145. def get_batch(self, obj):
  146. """ 动态序列化关联的批次数据 """
  147. from bound.models import BoundBatchModel
  148. return BoundBatchModel.objects.get(id=obj.batch_id).bound_number
  149. class ContainerDetailGetSerializer(serializers.ModelSerializer):
  150. # 定义明细单列表的序列化器,用于获取操作,字段只读
  151. month = serializers.IntegerField(read_only=True, required=False)
  152. container = serializers.SerializerMethodField()
  153. batch = serializers.SerializerMethodField()
  154. bound_number = serializers.SerializerMethodField()
  155. goods_code = serializers.CharField(read_only=True, required=False)
  156. goods_desc = serializers.CharField(read_only=True, required=False)
  157. goods_qty = serializers.DecimalField(read_only=False, required=False, max_digits=10, decimal_places=3)
  158. goods_weight = serializers.DecimalField(read_only=True, required=False, max_digits=10, decimal_places=2)
  159. goods_class = serializers.IntegerField(read_only=True, required=False)
  160. status = serializers.IntegerField(read_only=True, required=False)
  161. creater = serializers.CharField(read_only=True, required=False)
  162. create_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M', required=False)
  163. update_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M', required=False)
  164. def get_container(self, obj):
  165. """ 动态序列化关联的主单数据 """
  166. from .serializers import ContainerListGetSerializer
  167. return ContainerListGetSerializer(obj.container).data
  168. def get_batch(self, obj):
  169. """ 动态序列化关联的批次数据 """
  170. from bound.serializers import BoundBatchGetSerializer
  171. return BoundBatchGetSerializer(obj.batch).data
  172. def get_bound_number(self, obj):
  173. """ 动态序列化关联的批次数据 """
  174. from bound.models import BoundBatchModel
  175. return BoundBatchModel.objects.get(id=obj.batch_id).bound_number
  176. class Meta:
  177. # 指定模型和排除字段
  178. model = ContainerDetailModel
  179. fields= '__all__'
  180. read_only_fields = ['id']
  181. class ContainerDetailPutSerializer(serializers.ModelSerializer):
  182. # 定义明细单列表的序列化器,用于创建操作,允许部分字段写入
  183. month = serializers.IntegerField(read_only=False, required=False, validators=[datasolve.data_validate])
  184. goods_code = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  185. goods_desc = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  186. goods_qty = serializers.DecimalField(read_only=False, required=True, max_digits=10, decimal_places=3,validators=[datasolve.data_validate])
  187. goods_out_qty = serializers.DecimalField(read_only=False, required=True, max_digits=10, decimal_places=3,validators=[datasolve.data_validate])
  188. class Meta:
  189. # 指定模型和排除字段
  190. model = ContainerDetailModel
  191. fields= ['month','goods_code','goods_desc','goods_qty','goods_out_qty']
  192. read_only_fields = ['id']
  193. class ContainerDetailPostSerializer(serializers.ModelSerializer):
  194. # 定义明细单列表的序列化器,用于创建操作,允许部分字段写入
  195. month = serializers.IntegerField(read_only=False, required=False, validators=[datasolve.data_validate])
  196. container = serializers.PrimaryKeyRelatedField(queryset=ContainerListModel.objects.all(),
  197. help_text='关联的主单',
  198. error_messages = {
  199. 'null': '请选择关联的主单',
  200. 'does_not_exist': '关联的主单不存在',
  201. 'incorrect_type': '关联的主单格式错误'
  202. },
  203. required=False, validators=[datasolve.data_validate])
  204. batch = serializers.PrimaryKeyRelatedField(queryset=BoundBatchModel.objects.all(),
  205. help_text='关联的批次',
  206. error_messages = {
  207. 'does_not_exist': '关联的批次不存在',
  208. 'incorrect_type': '关联的批次格式错误'
  209. },
  210. required=False, validators=[datasolve.data_validate])
  211. goods_code = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  212. goods_desc = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  213. goods_qty = serializers.DecimalField(read_only=False, required=True, max_digits=10, decimal_places=3,validators=[datasolve.data_validate])
  214. goods_weight = serializers.DecimalField(read_only=False, required=True, max_digits=10, decimal_places=2, validators=[datasolve.data_validate])
  215. status = serializers.IntegerField(read_only=False, required=False, validators=[datasolve.data_validate])
  216. creater = serializers.CharField(read_only=False, required=False, validators=[datasolve.data_validate])
  217. create_time = serializers.DateTimeField(read_only=False, format='%Y-%m-%d %H:%M', required=False, validators=[datasolve.data_validate])
  218. update_time = serializers.DateTimeField(read_only=False, format='%Y-%m-%d %H:%M', required=False, validators=[datasolve.data_validate])
  219. class Meta:
  220. # 指定模型和排除字段
  221. model = ContainerDetailModel
  222. fields= '__all__'
  223. read_only_fields = ['id']
  224. class ContainerOperationGetSerializer(serializers.ModelSerializer):
  225. # 定义操作记录的序列化器,用于获取操作,字段只读
  226. month = serializers.IntegerField(read_only=True, required=False)
  227. container = serializers.SerializerMethodField()
  228. operation_type = serializers.CharField(read_only=True, required=False)
  229. batch = serializers.SerializerMethodField()
  230. goods_code = serializers.CharField(read_only=True, required=False)
  231. goods_desc = serializers.CharField(read_only=True, required=False)
  232. goods_qty = serializers.DecimalField(read_only=False, required=False, max_digits=10, decimal_places=3)
  233. goods_weight = serializers.DecimalField(read_only=True, required=False, max_digits=10, decimal_places=2)
  234. operator = serializers.CharField(read_only=True, required=False)
  235. timestamp = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M', required=False)
  236. from_location = serializers.CharField(read_only=True, required=False)
  237. to_location = serializers.CharField(read_only=True, required=False)
  238. memo = serializers.CharField(read_only=True, required=False)
  239. def get_container(self, obj):
  240. """ 动态序列化关联的主单数据 """
  241. from .serializers import ContainerListGetSerializer
  242. return ContainerListGetSerializer(obj.container).data
  243. def get_batch(self, obj):
  244. """ 动态序列化关联的批次数据 """
  245. from bound.serializers import BoundBatchGetSerializer
  246. return BoundBatchGetSerializer(obj.batch).data
  247. class Meta:
  248. # 指定模型和排除字段
  249. model = ContainerOperationModel
  250. fields= '__all__'
  251. read_only_fields = ['id']
  252. class ContainerOperationPostSerializer(serializers.ModelSerializer):
  253. # 定义操作记录的序列化器,用于创建操作,允许部分字段写入
  254. month = serializers.IntegerField(read_only=False, required=False, validators=[datasolve.data_validate])
  255. container = serializers.PrimaryKeyRelatedField(queryset=ContainerListModel.objects.all(),
  256. help_text='关联的主单',
  257. error_messages = {
  258. 'null': '请选择关联的主单',
  259. 'does_not_exist': '关联的主单不存在',
  260. 'incorrect_type': '关联的主单格式错误'
  261. },
  262. required=True, validators=[datasolve.data_validate])
  263. operation_type = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  264. batch = serializers.PrimaryKeyRelatedField(queryset=BoundBatchModel.objects.all(),
  265. help_text='关联的批次',
  266. error_messages = {
  267. 'null': '请选择关联的批次',
  268. 'does_not_exist': '关联的批次不存在',
  269. 'incorrect_type': '关联的批次格式错误'
  270. },
  271. required=False, validators=[datasolve.data_validate])
  272. goods_code = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  273. goods_desc = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  274. goods_qty = serializers.DecimalField(read_only=False, required=True, max_digits=10, decimal_places=3,validators=[datasolve.data_validate])
  275. goods_weight = serializers.DecimalField(read_only=False, required=True, max_digits=10, decimal_places=2, validators=[datasolve.data_validate])
  276. operator = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  277. timestamp = serializers.DateTimeField(read_only=False, format='%Y-%m-%d %H:%M', required=True, validators=[datasolve.data_validate])
  278. from_location = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  279. to_location = serializers.CharField(read_only=False, required=True, validators=[datasolve.data_validate])
  280. memo = serializers.CharField(read_only=False, required=False, validators=[datasolve.data_validate])
  281. class Meta:
  282. # 指定模型和排除字段
  283. model = ContainerOperationModel
  284. fields= '__all__'
  285. read_only_fields = ['id']
  286. class TaskGetSerializer(serializers.ModelSerializer):
  287. # 定义任务记录的序列化器,用于获取操作,字段只读
  288. task_wcs = serializers.SerializerMethodField()
  289. container_detail = serializers.SerializerMethodField()
  290. batch_detail = serializers.SerializerMethodField()
  291. def get_task_wcs(self, obj):
  292. """ 动态序列化关联的WCS任务数据 """
  293. from .models import ContainerWCSModel
  294. return ContainerWCSModel.objects.filter(id=obj.task_wcs_id).first().to_dict()
  295. def get_container_detail(self, obj):
  296. """ 动态序列化关联的主单数据 """
  297. from .serializers import ContainerDetailGetSerializer
  298. return ContainerDetailGetSerializer(obj.container_detail).data
  299. def get_batch_detail(self, obj):
  300. """ 动态序列化关联的批次数据 """
  301. from bound.serializers import BoundDetailGetSerializer
  302. return BoundDetailGetSerializer(obj.batch_detail).data
  303. class Meta:
  304. # 指定模型和排除字段
  305. model = TaskModel
  306. fields= '__all__'
  307. read_only_fields = ['id']
  308. class TaskPostSerializer(serializers.ModelSerializer):
  309. # 定义任务记录的序列化器,用于获取操作,字段只读
  310. task_wcs = serializers.PrimaryKeyRelatedField(queryset=ContainerWCSModel.objects.all(),
  311. help_text='关联的WCS任务',
  312. error_messages = {
  313. 'null': '请选择关联的WCS任务',
  314. 'does_not_exist': '关联的WCS任务不存在',
  315. 'incorrect_type': '关联的WCS任务格式错误'
  316. },
  317. required=False, validators=[datasolve.data_validate])
  318. bound_detail = serializers.PrimaryKeyRelatedField(queryset=BoundDetailModel.objects.all(),
  319. help_text='关联的明细单',
  320. error_messages = {
  321. 'null': '请选择关联的明细单',
  322. 'does_not_exist': '关联的明细单不存在',
  323. 'incorrect_type': '关联的明细单格式错误'
  324. },
  325. required=False, validators=[datasolve.data_validate])
  326. class Meta:
  327. # 指定模型和排除字段
  328. model = TaskModel
  329. fields= '__all__'
  330. read_only_fields = ['id']
  331. # serializers.py
  332. class OutBoundDetailSerializer(serializers.ModelSerializer):
  333. """列表用简略序列化器"""
  334. class Meta:
  335. model = out_batch_detail
  336. fields = ['id', 'out_bound', 'container', 'working']
  337. class OutBoundFullDetailSerializer(serializers.ModelSerializer):
  338. container_code = serializers.CharField(source='container.container_code', read_only=True)
  339. batch = serializers.CharField(source='container_detail.batch.bound_number', read_only=True)
  340. goods_code = serializers.CharField(source='container_detail.goods_code', read_only=True)
  341. goods_desc = serializers.CharField(source='container_detail.goods_desc', read_only=True)
  342. goods_qty = serializers.DecimalField(source='container_detail.goods_qty', read_only=True,max_digits=10, decimal_places=3)
  343. class Meta:
  344. model = out_batch_detail
  345. fields = '__all__'
  346. read_only_fields = ['id', 'out_bound', 'container', 'container_detail', 'working']
  347. class DispatchConfigSerializer(serializers.ModelSerializer):
  348. class Meta:
  349. model = DispatchConfig
  350. fields = ['id', 'cross_floor_concurrent_limit', 'intra_floor_order', 'enabled', 'update_time']
  351. read_only_fields = ['id', 'update_time']
  352. class WCSTaskLogSerializer(serializers.ModelSerializer):
  353. time = serializers.DateTimeField(source='send_time', format='%Y-%m-%d %H:%M:%S', read_only=True)
  354. taskNumber = serializers.IntegerField(source='task_number', read_only=True)
  355. class Meta:
  356. model = WCSTaskLogModel
  357. fields = [
  358. 'id', 'time', 'taskNumber', 'container', 'current_location',
  359. 'target_location', 'location_group_id',
  360. 'left_priority', 'right_priority', 'task_type', 'order_number',
  361. 'sequence', 'response_data', 'send_time', 'floor', 'is_completed', 'log_type'
  362. ]
  363. read_only_fields = ['id', 'send_time']