|
@@ -1051,6 +1051,7 @@ class ContainerDetailViewSet(viewsets.ModelViewSet):
|
|
|
"code": 200,
|
|
|
"message": "Success",
|
|
|
"data": {
|
|
|
+ "container_code": container.container_code,
|
|
|
"count": len(results),
|
|
|
"results": results,
|
|
|
"batch_totals": batch_totals # 可选:单独返回批次总量
|
|
@@ -1065,6 +1066,111 @@ class ContainerDetailViewSet(viewsets.ModelViewSet):
|
|
|
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
|
)
|
|
|
|
|
|
+
|
|
|
+ def pdadetail_list(self, request):
|
|
|
+ """
|
|
|
+ 获取PDA组盘入库的容器详情列表
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ container_code = request.query_params.get('container_code')
|
|
|
+ if not container_code:
|
|
|
+ return Response(
|
|
|
+ {'code': 400, 'message': '缺少托盘编码参数', 'data': None},
|
|
|
+ status=status.HTTP_200_OK
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+ # 获取容器对象
|
|
|
+ try:
|
|
|
+ container = ContainerListModel.objects.get(container_code=container_code)
|
|
|
+ except ContainerListModel.DoesNotExist:
|
|
|
+ return Response(
|
|
|
+ {'code': 404, 'message': '指定托盘不存在', 'data': None},
|
|
|
+ status=status.HTTP_200_OK
|
|
|
+ )
|
|
|
+
|
|
|
+ # 查询关联批次明细(排除状态0和3)
|
|
|
+ details = ContainerDetailModel.objects.filter(
|
|
|
+ container=container,is_delete=False
|
|
|
+ ).exclude(
|
|
|
+ status__in=[0, 3]
|
|
|
+ ).select_related('batch')
|
|
|
+
|
|
|
+ if not details.exists():
|
|
|
+ return Response(
|
|
|
+ {'code': 404, 'message': '未找到有效批次数据', 'data': None},
|
|
|
+ status=status.HTTP_200_OK
|
|
|
+ )
|
|
|
+
|
|
|
+ # 按批次号 + 数量分组统计
|
|
|
+ batch_dict = {}
|
|
|
+ batch_qty_dict = defaultdict(int) # 使用默认字典自动初始化
|
|
|
+
|
|
|
+ for detail in details:
|
|
|
+ if not detail.batch:
|
|
|
+ continue
|
|
|
+
|
|
|
+ bound_number = detail.batch.bound_number
|
|
|
+ goods_qty = detail.goods_qty - detail.goods_out_qty # 剔除出库数量
|
|
|
+
|
|
|
+ # 组合键:批次号 + 当前数量
|
|
|
+ batch_key = (bound_number, goods_qty)
|
|
|
+
|
|
|
+
|
|
|
+ batch_qty_dict[bound_number] += goods_qty # 自动处理键初始化
|
|
|
+
|
|
|
+ # 分组统计
|
|
|
+ if batch_key not in batch_dict:
|
|
|
+ batch_obj = BoundBatchModel.objects.filter( bound_number=bound_number).first()
|
|
|
+ batch_dict[batch_key] = {
|
|
|
+ "goods_code": detail.goods_code,
|
|
|
+ "goods_desc": detail.goods_desc,
|
|
|
+ "goods_qty": goods_qty,
|
|
|
+ "goods_class": detail.goods_class,
|
|
|
+ "goods_package": batch_obj.goods_package,
|
|
|
+ "batch_total_qty": batch_obj.goods_qty,
|
|
|
+ "batch_total_in_qty": batch_obj.goods_in_qty - batch_obj.goods_out_qty,
|
|
|
+ "status": detail.status,
|
|
|
+ "group_qty": 1,
|
|
|
+ "create_time": detail.create_time,
|
|
|
+ }
|
|
|
+ else:
|
|
|
+ batch_dict[batch_key]["group_qty"] += 1
|
|
|
+
|
|
|
+ # 重构数据结构
|
|
|
+ results = []
|
|
|
+ for (bound_number, qty), data in batch_dict.items():
|
|
|
+ results.append({
|
|
|
+ **data,
|
|
|
+ "bound_number": bound_number,
|
|
|
+ "current_qty": qty,
|
|
|
+ "total_batch_qty": batch_qty_dict[bound_number] # 添加批次总量
|
|
|
+ })
|
|
|
+ batch_totals =[]
|
|
|
+ for bound_number, qty in batch_qty_dict.items():
|
|
|
+ batch_totals.append({
|
|
|
+ "bound_number": bound_number,
|
|
|
+ "total_batch_qty": qty
|
|
|
+ })
|
|
|
+
|
|
|
+ return Response(
|
|
|
+ {
|
|
|
+ "code": 200,
|
|
|
+ "message": "Success",
|
|
|
+ "data": {
|
|
|
+ "count": len(results),
|
|
|
+ "results": results,
|
|
|
+ "batch_totals": batch_totals # 可选:单独返回批次总量
|
|
|
+ }
|
|
|
+ },
|
|
|
+ status=status.HTTP_200_OK
|
|
|
+ )
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ return Response(
|
|
|
+ {'code': 500, 'message': f'服务器错误: {str(e)}', 'data': None},
|
|
|
+ status=status.HTTP_200_OK
|
|
|
+ )
|
|
|
# 托盘操作历史记录
|
|
|
class ContainerOperateViewSet(viewsets.ModelViewSet):
|
|
|
"""
|
|
@@ -1196,7 +1302,7 @@ class OutboundService:
|
|
|
|
|
|
# 发送关键请求
|
|
|
response = requests.post(
|
|
|
- "http://192.168.18.67:1616/wcs/WebApi/getOutTask",
|
|
|
+ "http://192.168.18.200:1616/wcs/WebApi/getOutTask",
|
|
|
json=send_data,
|
|
|
timeout=10
|
|
|
)
|
|
@@ -1249,7 +1355,7 @@ class OutboundService:
|
|
|
tasknumber = month*100000+tasknumber_index+tasknumber,
|
|
|
container=container_obj.container_code,
|
|
|
current_location=container_obj.current_location,
|
|
|
- target_location="203",
|
|
|
+ target_location="103",
|
|
|
tasktype="outbound",
|
|
|
month=int(timezone.now().strftime("%Y%m")),
|
|
|
message="等待出库",
|
|
@@ -1597,6 +1703,7 @@ class OutTaskViewSet(APIView):
|
|
|
if left_qty - allocate_qty >= 0:
|
|
|
break
|
|
|
add_qty = min(allocate_qty-left_qty, cd.goods_qty - cd.goods_out_qty)
|
|
|
+ last_out_qty = cd.goods_out_qty
|
|
|
cd.goods_out_qty += add_qty
|
|
|
left_qty += add_qty
|
|
|
cd.save()
|
|
@@ -1609,6 +1716,7 @@ class OutTaskViewSet(APIView):
|
|
|
container_id=cd.container_id,
|
|
|
container_detail_id=cd.id,
|
|
|
out_goods_qty=add_qty,
|
|
|
+ last_out_goods_qty = last_out_qty,
|
|
|
working = 1,
|
|
|
is_delete = False
|
|
|
)
|
|
@@ -1741,4 +1849,90 @@ class OutDetailViewSet(viewsets.ModelViewSet):
|
|
|
"""根据action切换序列化器"""
|
|
|
if self.action == 'retrieve':
|
|
|
return OutBoundFullDetailSerializer
|
|
|
- return super().get_serializer_class()
|
|
|
+ return super().get_serializer_class()
|
|
|
+
|
|
|
+ def get_out_batch_detail(self, request):
|
|
|
+ """获取某个容器的出库明细"""
|
|
|
+ try:
|
|
|
+ container_code = request.query_params.get('container_code')
|
|
|
+ container_obj = ContainerListModel.objects.filter(container_code=container_code).first()
|
|
|
+ if not container_obj:
|
|
|
+ return Response({"code": "500", "message": f"容器 {container_code} 不存在"}, status=status.HTTP_200_OK)
|
|
|
+ out_batch_detail_all = out_batch_detail.objects.filter(container=container_obj,working=1,is_delete=False).all()
|
|
|
+ if not out_batch_detail_all:
|
|
|
+ return Response({"code": "500", "message": f"容器 {container_code} 无出库明细"}, status=status.HTTP_200_OK)
|
|
|
+ serializer = OutBoundFullDetailSerializer(out_batch_detail_all, many=True)
|
|
|
+ return Response({"code": "200", "message": "Success", "data": serializer.data}, status=status.HTTP_200_OK)
|
|
|
+ except Exception as e:
|
|
|
+ return Response({"code": "500", "message": str(e)}, status=status.HTTP_200_OK)
|
|
|
+
|
|
|
+ def confirm_out_batch_detail(self, request):
|
|
|
+ """确认出库"""
|
|
|
+ try:
|
|
|
+
|
|
|
+ container_code = request.query_params.get('container_code')
|
|
|
+ container_obj = ContainerListModel.objects.filter(container_code=container_code).first()
|
|
|
+ if not container_obj:
|
|
|
+ return Response({"code": "500", "message": f"容器 {container_code} 不存在"}, status=status.HTTP_200_OK)
|
|
|
+ out_batch_detail_all = out_batch_detail.objects.filter(container=container_obj,working=1,is_delete=False).all()
|
|
|
+ if not out_batch_detail_all:
|
|
|
+ return Response({"code": "500", "message": f"容器 {container_code} 无出库明细"}, status=status.HTTP_200_OK)
|
|
|
+ for obj in out_batch_detail_all:
|
|
|
+ obj.working = 0
|
|
|
+ obj.save()
|
|
|
+ BatchLogModel.objects.create(
|
|
|
+ batch_id = obj.container_detail.batch,
|
|
|
+ log_type = 1,
|
|
|
+ log_date = timezone.now(),
|
|
|
+ goods_code = obj.container_detail.batch.goods_code,
|
|
|
+ goods_desc = obj.container_detail.batch.goods_desc,
|
|
|
+ goods_qty = obj.out_goods_qty,
|
|
|
+ log_content = f"出库容器 {container_code} 批次 {obj.container_detail.batch.id} 数量 {obj.out_goods_qty} 重量 {obj.container_detail.batch.goods_weight} 到 {obj.to_location.location_code} 库位",
|
|
|
+ creater = "WMS",
|
|
|
+ openid = "WMS"
|
|
|
+
|
|
|
+ )
|
|
|
+ return Response({"code": "200", "message": "出库成功"}, status=status.HTTP_200_OK)
|
|
|
+ except Exception as e:
|
|
|
+ return Response({"code": "500", "message": str(e)}, status=status.HTTP_200_OK)
|
|
|
+
|
|
|
+ def cancel_out_batch_detail(self, request):
|
|
|
+ """取消出库"""
|
|
|
+ try:
|
|
|
+ container_code = request.query_params.get('container_code')
|
|
|
+ container_obj = ContainerListModel.objects.filter(container_code=container_code).first()
|
|
|
+ if not container_obj:
|
|
|
+ return Response({"code": "500", "message": f"容器 {container_code} 不存在"}, status=status.HTTP_200_OK)
|
|
|
+ out_batch_detail_all = out_batch_detail.objects.filter(container=container_obj,working=1,is_delete=False).all()
|
|
|
+ if not out_batch_detail_all:
|
|
|
+ return Response({"code": "500", "message": f"容器 {container_code} 无出库明细"}, status=status.HTTP_200_OK)
|
|
|
+ for obj in out_batch_detail_all:
|
|
|
+ obj.container_detail.goods_out_qty = obj.last_out_goods_qty
|
|
|
+ obj.container_detail.save()
|
|
|
+ obj.is_delete = True
|
|
|
+ obj.working = 0
|
|
|
+ obj.save()
|
|
|
+ return Response({"code": "200", "message": "出库取消成功"}, status=status.HTTP_200_OK)
|
|
|
+ except Exception as e:
|
|
|
+ return Response({"code": "500", "message": str(e)}, status=status.HTTP_200_OK)
|
|
|
+
|
|
|
+ def get_contianer_detail(self, request):
|
|
|
+ try:
|
|
|
+ container_code = request.query_params.get('container_code')
|
|
|
+ container_obj = ContainerListModel.objects.filter(container_code=container_code).first()
|
|
|
+ if not container_obj:
|
|
|
+ return Response({"code": "500", "message": f"容器 {container_code} 不存在"}, status=status.HTTP_200_OK)
|
|
|
+ container_detail_all = ContainerDetailModel.objects.filter(container=container_obj,is_delete=False).all().exclude(status__in=[3])
|
|
|
+ return_data=[]
|
|
|
+ for obj in container_detail_all:
|
|
|
+ return_data.append({
|
|
|
+ "id": obj.id,
|
|
|
+ "batch": obj.batch.bound_number,
|
|
|
+ "goods_code": obj.goods_code,
|
|
|
+ "goods_desc": obj.goods_desc,
|
|
|
+ "goods_qty" :obj.goods_qty,
|
|
|
+ "out_goods_qty": obj.goods_out_qty
|
|
|
+ })
|
|
|
+ return Response({"code": "200", "message": "Success", "data": return_data}, status=status.HTTP_200_OK)
|
|
|
+ except Exception as e:
|
|
|
+ return Response({"code": "500", "message": str(e)}, status=status.HTTP_200_OK)
|