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 from bin.queries import LocationQueries LocationQueries.get_batch_info(data.get('container_code')) 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)