123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- from django.db import transaction
- from rest_framework.response import Response
- from rest_framework.views import APIView
- from django.utils import timezone
- from .models import ContainerListModel,ContainerDetailModel,ContainerOperationModel,TaskModel,ContainerWCSModel
- from bound.models import BoundBatchModel,BoundDetailModel,BoundListModel
- from .serializers import *
- class ContainerService:
- """
- 托盘管理服务
- function:
- create_container_operation: 创建托盘操作记录
- """
- @staticmethod
- @transaction.atomic
- def create_container_operation(data, logger):
-
- # 初始化基础数据
- data['month'] = timezone.now().strftime('%Y%m')
-
- # 处理容器
- container = ContainerManager.get_or_create_container(
- container_code=data.get('container'),
- logger=logger
- )
- data['container_code'] = container.container_code
- data['container'] = container.id
- # 处理批次数据
- if data.get('goods_class') == 2:
- return BatchProcessor.handle_special_batches(data, logger)
- return BatchProcessor.handle_normal_batches(data, logger)
- class ContainerManager:
- @staticmethod
- def get_or_create_container(container_code, logger):
- """统一管理容器对象"""
- if container := ContainerListModel.objects.filter(container_code=container_code).first():
- logger.info(f"托盘 {container_code} 已存在")
- return container
-
- logger.info(f"创建新托盘 {container_code}")
- serializer = ContainerListPostSerializer(data={'container_code': container_code})
- serializer.status = 5
- serializer.is_valid(raise_exception=True)
- serializer.save()
- return ContainerListModel.objects.filter(container_code=container_code).first()
- class BatchProcessor:
- @staticmethod
- def handle_normal_batches(data, logger):
- """标准批次处理流程"""
- for batch in data.get('batches', []):
- try:
- BatchOperator.process_single_batch(data, batch, logger)
- except Exception as e:
- logger.error(f"批次处理失败: {str(e)}")
- continue
- return Response({"status": "success"})
- @staticmethod
- def handle_special_batches(data, logger):
- """托盘组处理流程"""
- for batch in data.get('batches', []):
- try:
- BatchOperator.process_single_container(data, batch, logger)
- except Exception as e:
- logger.error(f"托盘组处理失败: {str(e)}")
- continue
- return Response({"status": "success"})
- class BatchOperator:
- @staticmethod
- def process_single_container(data, batch, logger):
- """单个批次处理托盘"""
- # 获取批次对象
- container_obj = ContainerManager.get_or_create_container(
- batch.get('goods_code'),
- logger
- )
- # 更新批次状态
- update_result = BatchStatusUpdater.update_container_status(
- container_obj,
- 5,
- data.get('container_code'),
- )
- print(update_result)
- # 创建托盘关联记录
- RecordCreator.create_container_related_records(
- data=data,
- container_obj=container_obj
- )
- @staticmethod
- def process_single_batch(data, batch, logger):
- """单个批次处理批次"""
- # 获取批次对象
- bound_obj = BatchValidator.get_valid_batch(
- batch.get('goods_code'),
- logger
- )
-
- # 更新批次状态(新增数目)
- update_result = BatchStatusUpdater.update_status(
- bound_obj,
- batch['goods_qty'] * batch['goods_group'],
- logger
- )
-
- # 创建关联记录
- RecordCreator.create_related_records(
- data=data,
- bound_obj=bound_obj,
- batch_data= batch,
- qty_diff=update_result['added_qty'],
- logger=logger
- )
- class BatchValidator:
- @staticmethod
- def get_valid_batch(bound_number, logger):
- """批次校验模块"""
- if not (bound_obj := BoundBatchModel.objects.filter(bound_number=bound_number).first()):
- logger.error(f"批次 {bound_number} 不存在")
- raise ValueError("无效批次号")
- return bound_obj
- class BatchStatusUpdater:
- @staticmethod
- def update_status(bound_obj, added_qty, logger):
- """批次状态管理"""
- last_qty = bound_obj.goods_in_qty
- bound_obj.goods_in_qty += added_qty
-
- if bound_obj.goods_in_qty >= bound_obj.goods_qty:
- FullBatchHandler.mark_as_completed(bound_obj, logger)
- else:
- bound_obj.status = 0
-
- bound_obj.save()
- return {
- 'last_qty': last_qty,
- 'added_qty': added_qty
- }
- @staticmethod
- def update_container_status(container_obj, status, container_code):
- """批次状态管理"""
-
- container_obj.status = status
- container_obj.available = False
- container_obj.current_location = '托盘'+str(container_code)
- container_obj.save()
- return {
- 'last_qty': 1,
- 'added_qty': 1
- }
-
- class FullBatchHandler:
- @staticmethod
- def mark_as_completed(bound_obj, logger):
- """满批次处理"""
- # bound_obj.goods_in_qty = bound_obj.goods_qty
- bound_obj.status = 1
- BatchRelationUpdater.update_related_records(bound_obj, logger)
- class BatchRelationUpdater:
- @staticmethod
- def update_related_records(bound_obj, logger):
- """更新关联单据"""
- if detail := BoundDetailModel.objects.filter(bound_batch=bound_obj.id).first():
- detail.status = 1
- detail.save()
- CompletionChecker.check_list_completion(detail.bound_list_id, logger)
- class CompletionChecker:
- @staticmethod
- def check_list_completion(list_id, logger):
- """完成度检查"""
- completed = BoundDetailModel.objects.filter(bound_list=list_id, status=1).count()
- total = BoundDetailModel.objects.filter(bound_list=list_id).count()
-
- if completed == total:
- ListStatusUpdater.update_list_status(list_id, 102, logger)
- class ListStatusUpdater:
- @staticmethod
- def update_list_status(list_id, status, logger):
- """更新单据状态"""
- if list_obj := BoundListModel.objects.filter(id=list_id).first():
- list_obj.bound_status = status
- list_obj.save()
- logger.info("入库申请全部完成")
- class RecordCreator:
- @staticmethod
- def create_container_related_records(data, container_obj, qty_diff=1):
- """记录创建批次"""
- # 生成明细记录
- detail_data = RecordBuilder.build_detail_data_container_group(
- data=data,
- container_obj=container_obj,
- qty_diff=qty_diff
- )
- DetailRecordCreator.create_container_related_records(detail_data)
-
- # 生成操作记录
- operation_data = RecordBuilder.build_operation_data_container_group(
- detail_data=detail_data,
- qty_diff=qty_diff
- )
- OperationRecordCreator.create_container_related_operation_records(operation_data)
- @staticmethod
- def create_related_records(data, bound_obj, batch_data, qty_diff, logger):
- """记录创建批次"""
- # 生成明细记录
- goods_group = batch_data.get('goods_group')
- goods_qty = batch_data.get('goods_qty')
- for i in range(goods_group):
- detail_data = RecordBuilder.build_detail_data(
- data=data,
- bound_obj=bound_obj,
- qty_diff=goods_qty
- )
- DetailRecordCreator.create_record(detail_data)
-
- # 生成操作记录
- operation_data = RecordBuilder.build_operation_data(
- detail_data=detail_data,
- qty_diff=qty_diff
- )
- OperationRecordCreator.create_operation_record(operation_data)
- class RecordBuilder:
- @staticmethod
- def build_detail_data(data, bound_obj, qty_diff):
- """构建明细数据结构"""
- return {
- "container": data['container'],
- "batch": bound_obj.id,
- "goods_code": bound_obj.goods_code,
- "goods_desc": bound_obj.goods_desc,
- "goods_qty": qty_diff,
- "goods_weight": bound_obj.goods_weight,
- "status": 1,
- "month": data['month'],
- "creater": data.get('creater', 'wms')
- }
-
- @staticmethod
- def build_detail_data_container_group(data, container_obj, qty_diff=1):
- """构建明细数据结构"""
- return {
- "container": data['container'],
- "goods_code": container_obj.container_code,
- "goods_desc": '托盘组',
- "goods_qty": qty_diff,
- "goods_weight": 0,
- "status": 1,
- "month": data['month'],
- "creater": data.get('creater', 'wms')
- }
- @staticmethod
- def build_operation_data(detail_data, qty_diff):
- """构建操作记录数据"""
- return {
- "month": detail_data['month'],
- "container": detail_data['container'],
- "operation_type": 'container',
- "batch": detail_data['batch'],
- "goods_code": detail_data['goods_code'],
- "goods_desc": detail_data['goods_desc'],
- "goods_qty": qty_diff,
- "goods_weight": qty_diff,
- "operator": detail_data['creater'],
- "timestamp": timezone.now(),
- "from_location": "container",
- "to_location": "container",
- "memo": f"每组{detail_data['goods_code']}数目{detail_data['goods_qty']},PDA组盘共计组盘{qty_diff}"
- }
-
- def build_operation_data_container_group(detail_data, qty_diff):
- """构建操作记录数据"""
- return {
- "month": detail_data['month'],
- "container": detail_data['container'],
- "operation_type": 'container',
- "goods_code": detail_data['goods_code'],
- "goods_desc": detail_data['goods_desc'],
- "goods_qty": qty_diff,
- "goods_weight": detail_data['goods_weight'],
- "operator": detail_data['creater'],
- "timestamp": timezone.now(),
- "from_location": "container",
- "to_location": "container",
- "memo": f"托盘组下的:{detail_data['goods_code']}合盘"
- }
- class DetailRecordCreator:
- @staticmethod
- def create_record(data):
- """统一创建明细记录"""
- serializer = ContainerDetailPostSerializer(data=data)
- serializer.is_valid(raise_exception=True)
- serializer.save()
- def create_container_related_records(data):
- """记录创建批次"""
- # 生成明细记录
- container_obj = ContainerListModel.objects.filter(id=data['container']).first()
- container_obj.status = 5
- container_obj.save()
- if ContainerDetailModel.objects.filter(container=container_obj,goods_code=data['goods_code'],status=1,is_delete=False).first():
- return
- ContainerDetailModel.objects.create(
- container=container_obj,
- goods_code=data['goods_code'],
- goods_desc=data['goods_desc'],
- goods_qty=data['goods_qty'],
- goods_weight=data['goods_weight'],
- goods_class=2,
- status=data['status'],
- month=data['month'],
- creater=data['creater']
- )
- class OperationRecordCreator:
- @staticmethod
- def create_operation_record(data):
- """统一创建操作记录"""
- serializer = ContainerOperationPostSerializer(data=data)
- serializer.is_valid(raise_exception=True)
- serializer.save()
- @staticmethod
- def create_container_related_operation_records(data):
- container_obj = ContainerListModel.objects.filter(id=data['container']).first()
- if ContainerOperationModel.objects.filter(container_id=container_obj.id,goods_code=data['goods_code'],is_delete=False).first():
- return
- ContainerOperationModel.objects.create(
- month=data['month'],
- container_id=container_obj.id,
- operation_type=data['operation_type'],
- bound_id=None,
- goods_code=data['goods_code'],
- goods_desc=data['goods_desc'],
- goods_qty=data['goods_qty'],
- goods_weight=data['goods_weight'],
- operator=data['operator'],
- timestamp=data['timestamp'],
- from_location=data['from_location'],
- to_location=data['to_location'],
- memo=data['memo']
- )
- # 最终视图类
- class OperationView(APIView):
- def create(self, request, *args, **kwargs):
- try:
- return ContainerService.create_container_operation(
- data=request.data,
- logger=self.get_logger() # 假设有日志方法
- )
- except Exception as e:
- return Response({"error": str(e)}, status=400)
|