1
0
forked from erp-dev/erp

fix: rebuild stock change record

This commit is contained in:
2025-11-05 16:57:54 +08:00
parent d88bf367f8
commit a759030cdc
16 changed files with 1116 additions and 66 deletions

136
api_v1/views.py Normal file
View File

@@ -0,0 +1,136 @@
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from django.db import transaction
from typing import List, Dict, Any
import logging
from stock import models as stock_models
from basic_info import models as basic_info_models
from drf_spectacular.utils import extend_schema
from . import serializers
logger = logging.getLogger(__name__)
@extend_schema(tags=['创建出入库'])
@api_view(['POST'])
def create_full_stock_change(request):
"""
创建完整的库存变动记录(包含记录创建参数)
POST /api/v1/stock-change/
请求参数:
{
"type": 1, // 1=入库, 2=出库
"warehouse": 1, // 仓库ID
"source_type": 1, // 来源类型
"source_id": 1, // 可选来源单据ID
"products": [
{
"product": 1,
"quantity": [85, 75, 90]
}
]
}
"""
# 提取库存变动记录参数
record_data = {
'type': request.data.get('type'),
'warehouse': request.data.get('warehouse'),
'source_type': request.data.get('source_type'),
'source_id': request.data.get('source_id'),
}
# 验证必要参数
if not all([record_data['type'], record_data['warehouse'], record_data['source_type']]):
return Response({
'error': '缺少必要参数',
'message': '请提供 type, warehouse, source_type'
}, status=status.HTTP_400_BAD_REQUEST)
products_data = request.data.get('products', [])
if not products_data:
return Response({
'error': '产品列表不能为空'
}, status=status.HTTP_400_BAD_REQUEST)
# 验证产品数据
product_serializer = serializers.CreateStockChangeSerializer(data={
'products': products_data
})
if not product_serializer.is_valid():
return Response({
'error': '产品数据验证失败',
'details': product_serializer.errors
}, status=status.HTTP_400_BAD_REQUEST)
try:
with transaction.atomic():
# 1. 创建库存变动记录
try:
warehouse = basic_info_models.WareHouse.objects.get(id=record_data['warehouse'])
except basic_info_models.WareHouse.DoesNotExist:
return Response({
'error': f'仓库ID {record_data["warehouse"]} 不存在'
}, status=status.HTTP_400_BAD_REQUEST)
stock_change_record = stock_models.StockChangeRecord.objects.create(
type=record_data['type'],
warehouse=warehouse,
source_type=record_data['source_type'],
source_id=record_data['source_id'],
# created_by=request.user
)
logger.info(f"创建新库存变动记录 ID: {stock_change_record.id}")
# 2. 创建库存变动明细
created_details = []
created_count = 0
for product_data in products_data:
product_id = product_data['product']
quantities = product_data['quantity']
# 获取产品信息
try:
product = basic_info_models.Product.objects.get(id=product_id)
except basic_info_models.Product.DoesNotExist:
raise ValueError(f'产品ID {product_id} 不存在')
# 为每个数量创建明细记录
for quantity in quantities:
detail = stock_models.StockChangeDetail.objects.create(
stock_change_record=stock_change_record,
product=product,
quantity=quantity,
unit=product.unit
)
created_details.append(detail)
created_count += 1
# 3. 构建响应
response_serializer = serializers.CreateStockChangeResponseSerializer({
'stock_change_record': stock_change_record,
'details': created_details,
'message': f'成功创建库存变动记录及 {created_count} 条明细',
'created_details_count': created_count
})
return Response(response_serializer.data, status=status.HTTP_201_CREATED)
except ValueError as e:
return Response({
'error': str(e)
}, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
logger.error(f"创建完整库存变动记录失败: {str(e)}", exc_info=True)
return Response({
'error': '创建库存变动记录失败',
'message': str(e)
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)