入库的接口完成,但是没有测试

master
laoxiao 1 year ago
parent b778da06f1
commit 6a3ac097e8

@ -1,20 +1,26 @@
from django.db import transaction
from django.db.models import Sum
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from ERP_5.utils.get_inventory import get_inventory_by_goods
from purchase_info.models import PurchaseModel, PurchaseItemModel
from warehouse_info.models import PurchaseStorageItemModel
class PurchaseItemsSerializer(serializers.ModelSerializer):
"""
采购单中的项目 的序列化器
"""
model_number = serializers.CharField(source='goods.model_number', read_only=True)
color = serializers.CharField(source='goods.color', read_only=True)
nits_name = serializers.CharField(source='goods.units.basic_name', read_only=True)
cur_inventory = serializers.SerializerMethodField(read_only=True)
# 增加一个已经入库数量的序列化属性(未来在新增入库单的时候需要展示)
already_in_number = serializers.SerializerMethodField(read_only=True)
class Meta:
model = PurchaseItemModel
fields = '__all__'
@ -22,6 +28,15 @@ class PurchaseItemsSerializer(serializers.ModelSerializer):
def get_cur_inventory(self, obj):
return get_inventory_by_goods(obj.goods.id)
def get_already_in_number(self, obj):
# 先根据采购单ID作为一个过滤条件, 基于当前货品ID作为第二个过滤条件 而且入库单的状态是已经审核
in_count = PurchaseStorageItemModel.objects.filter(
purchase_storage__purchase__id=obj.purchase.id,
goods_id=obj.goods.id).exclude(purchase_storage__status='0')\
.aggregate(sum=Sum('purchase_count'))
if in_count:
return in_count['sum']
return 0
class PurchaseSerializer(serializers.ModelSerializer):
"""

@ -0,0 +1,91 @@
from django.db import transaction
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from ERP_5.utils.get_inventory import get_inventory_by_goods
from warehouse_info.models import PurchaseStorageModel, PurchaseStorageItemModel
class StorageItemSerializer(serializers.ModelSerializer):
"""
入库单的 项项目序列化
"""
# 注意:既然只有 库存数据没有,那么可以增加一个属性
cur_inventory = serializers.SerializerMethodField(read_only=True, label='在当前仓库中库存')
class Meta:
model = PurchaseStorageItemModel
fields = '__all__'
def get_cur_inventory(self, obj): # 当前的obj为PurchaseStorageItemModel对象
result = get_inventory_by_goods(obj.goods.id, obj.warehouse.id)
return result if result else 0
class StorageSerializer(serializers.ModelSerializer):
"""
入库单反序列化器用于新增和修改 查询列表的序列化器
"""
item_list = StorageItemSerializer(many=True)
# 采购订单列表中需要展示:商品信息。
goods_info = serializers.SerializerMethodField(read_only=True, label='列表中展示的商品信息')
class Meta:
model = PurchaseStorageModel
fields = '__all__'
def get_goods_info(self, obj):
"""
商品信息是由 商品1名称 商品1规格 , 商品2名称 商品2规格 ....
"""
if obj.item_list.all():
result = []
for item in obj.item_list.all():
result.append(item.name + (item.specification if item.specification else ''))
return ', '.join(result)
return ""
# 同时插入采购单和采购单中货品项。必须重写create
def create(self, validated_data):
item_list = validated_data.pop('item_list')
with transaction.atomic():
purchase_storage = PurchaseStorageModel.objects.create(**validated_data)
for item in item_list:
psi = PurchaseStorageItemModel.objects.create(purchase_storage=purchase_storage, **item)
# 把一些冗余属性也加进去
goods = item.get('goods')
psi.specification = goods.specification
psi.model_number = goods.model_number
psi.number_code = goods.number_code
psi.color = goods.color
psi.category = goods.category
psi.category_name = goods.category.name
psi.units = goods.units
psi.units_name = goods.units.basic_name
psi.save()
return purchase_storage
# 同时插入采购单和采购单中货品项。必须重写update
def update(self, instance, validated_data):
if instance.status == '1':
raise ValidationError("入库单已经生效,不能修改")
item_list = validated_data.pop('item_list')
old_list = instance.item_list.all()
with transaction.atomic():
if old_list.exists():
# 然后把旧数据删除因为在validated_data拿不到货品库存数据的ID
instance.item_list.all().delete()
for item in item_list: # 重新插入采购项 数据
psi = PurchaseStorageItemModel.objects.create(purchase_storage=instance, **item)
# 把一些冗余属性也加进去
goods = item.get('goods')
psi.specification = goods.specification
psi.model_number = goods.model_number
psi.number_code = goods.number_code
psi.color = goods.color
psi.category = goods.category
psi.category_name = goods.category.name
psi.units = goods.units
psi.units_name = goods.units.basic_name
psi.save()
result = super(StorageSerializer, self).update(instance=instance, validated_data=validated_data)
return result

@ -0,0 +1,180 @@
from django.db import transaction
from django.db.models import Q, F, Sum
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from ERP_5.utils.base_views import MultipleDestroyMixin, MultipleAuditMixin
from ERP_5.utils.paginations import GlobalPagination
from basic_info.models import SupplierModel
from erp_system.models import UserModel
from goods_info.models import GoodsInventoryModel
from warehouse_info.models import PurchaseStorageModel
from warehouse_info.serializer.in_storage_serializer import StorageSerializer
class InStorageViewSet(viewsets.ModelViewSet, MultipleDestroyMixin, MultipleAuditMixin):
"""
create:
仓库(采购)入库单--新增,注意其中images_list="1,2,3,4";里面是附件的ID
仓库(采购)入库单新增, status: 201(成功), return: 新增仓库(采购)入库单信息
destroy:
仓库(采购)入库单--删除
仓库(采购)入库单删除, status: 204(成功), return: None
multiple_delete:
仓库(采购)入库单--批量删除,必传参数ids=[1,2,3,4...]
仓库(采购)入库单批量删除, status: 204(成功), return: None
update:
仓库(采购)入库单--修改,注意其中images_list="1,2,3,4";里面是附件的ID
仓库(采购)入库单修改, status: 200(成功), return: 修改后的仓库(采购)入库单信息
partial_update:
仓库(采购)入库单--局部修改,可以传参任意属性的值服务器会修改指定的属性值
仓库(采购)入库单局部修改, status: 200(成功), return: 修改后的仓库(采购)入库单信息
list:
仓库(采购)入库单--该接口可以弃用
仓库(采购)入库单列表信息, status: 200(成功), return: 仓库(采购)入库单信息列表
retrieve:
查询某一个仓库(采购)入库单
查询指定ID的仓库(采购)入库单, status: 200(成功), return: 用户仓库(采购)入库单
"""
queryset = PurchaseStorageModel.objects.all()
serializer_class = StorageSerializer
pagination_class = GlobalPagination
def get_queryset(self):
if self.action == 'find': # 过滤查询
# 获取请求参数(在json中)
number_code = self.request.data.get('number_code', None)
keyword = self.request.data.get('keyword', None)
start_date = self.request.data.get('start_date', None)
end_date = self.request.data.get('start_date', None)
supplier = self.request.data.get('supplier', 0)
operator_user = self.request.data.get('operator_user', 0)
status = self.request.data.get('status', None)
warehouse = self.request.data.get('warehouse', 0)
account = self.request.data.get('account', 0)
purchase_number_code = self.request.data.get('purchase_number_code', None)
query = Q()
if keyword:
child_query = Q()
child_query.add(Q(item_list__name__contains=keyword), 'OR')
child_query.add(Q(item_list__specification=keyword), 'OR')
query.add(child_query, 'AND')
if warehouse:
query.add(Q(item_list__warehouse_id=warehouse), 'AND')
if account:
query.add(Q(account__id=account), 'AND')
if purchase_number_code:
query.add(Q(purchase__number_code__contains=purchase_number_code), 'AND')
if start_date:
query.add(Q(invoices_date__gt=start_date), 'AND')
if end_date:
query.add(Q(invoices_date__lt=end_date), 'AND')
if supplier:
query.add(Q(supplier__id=supplier), 'AND')
if number_code:
query.add(Q(number_code__contains=number_code), 'AND')
if operator_user:
query.add(Q(operator_user__id=operator_user), 'AND')
if status:
query.add(Q(status=status), 'AND')
return PurchaseStorageModel.objects.filter(query).distinct().all()
else:
return PurchaseStorageModel.objects.all()
params = openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'keyword': openapi.Schema(type=openapi.TYPE_STRING, description="名称的关键字或者型号"),
'start_date': openapi.Schema(type=openapi.TYPE_STRING, description="起始日期2020-10-01"),
'number_code': openapi.Schema(type=openapi.TYPE_STRING, description="编号(序列号)"),
'end_date': openapi.Schema(type=openapi.TYPE_STRING, description="结束日期2020-10-01"),
'status': openapi.Schema(type=openapi.TYPE_STRING, description="状态0或者1,2,3.."),
'supplier': openapi.Schema(type=openapi.TYPE_INTEGER, description="供应商的ID"),
'operator_user': openapi.Schema(type=openapi.TYPE_INTEGER, description="操作用户的ID"),
'warehouse': openapi.Schema(type=openapi.TYPE_INTEGER, description="仓库的ID"),
'account': openapi.Schema(type=openapi.TYPE_INTEGER, description="结算账户的ID"),
'purchase_number_code': openapi.Schema(type=openapi.TYPE_STRING, description="采购订单编号关键字"),
})
# 分页参数必须是query_param(看源码)
page_param = openapi.Parameter(name='page', in_=openapi.IN_QUERY, description="页号", type=openapi.TYPE_INTEGER)
size_param = openapi.Parameter(name='size', in_=openapi.IN_QUERY, description="每页显示数量", type=openapi.TYPE_INTEGER)
@swagger_auto_schema(method='POST', request_body=params, manual_parameters=[page_param, size_param],
operation_description="入库单的搜索过滤")
@action(methods=['POST'], detail=False)
def find(self, request, *args, **kwargs):
return super(InStorageViewSet, self).list(request=request, *args, **kwargs)
body_param = openapi.Schema(type=openapi.TYPE_OBJECT, required=['ids', 'user_id'], properties={
'ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_INTEGER),
description="选择哪些需要批量的ID主键列表"),
'user_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="审核人的用户ID"),
# 'is_audit': openapi.Schema(type=openapi.TYPE_STRING, description="是否审核审核1")
})
@swagger_auto_schema(method='put', request_body=body_param, operation_description="批量审核")
@action(methods=['put'], detail=False)
@transaction.atomic # 自动 数据库事务
def multiple_audit(self, request, *args, **kwargs):
audit_ids = request.data.get('ids')
user_id = request.data.get('user_id') # 用户ID
# is_audit = request.data.get('is_audit', '1') # 是否审核审核1
# 为了减少代码量,参数的验证就不写了
queryset = self.get_queryset().filter(id__in=audit_ids).all()
check_user = UserModel.objects.get(id=int(user_id))
for item in queryset:
# 条件是否成立
if item.status != '0': # 0以后的状态是不能审核的
return Response(data={'detail': '不能审核,因为订单已生效'}, status=status.HTTP_400_BAD_REQUEST)
if item.status == '0' and item.purchase:
if item.purchase.status != '1' and item.purchase.status != '2' and item.purchase.status != '5':
return Response(data={'detail': '不能审核,因为关联的采购订单未生效或者已经入库完成'}, status=status.HTTP_400_BAD_REQUEST)
# 处理审核的业务
if item.this_debt: # 如果有欠款,需要修改供应商的期末应付
SupplierModel.objects.filter(id=item.supplier_id).update(current_pay=F('current_pay') + item.this_debt)
if item.purchase: # 如果关联到采购单,需要修改采购单的状态为:部分入库或者全部入库
# 先去查询已经入库的数量
in_count_dict = PurchaseStorageModel.objects \
.filter(purchase_id=item.purchase_id) \
.exclude(status=0) \
.aggregate(my_sum=Sum('number_count'))
in_count = 0
if in_count_dict:
in_count = in_count_dict['my_sum']
# 第一种情况: 已经入库数量 + 当前正在入库的数量 == 采购总数量。
if (in_count + item.number_count) == item.purchase.number_count:
item.purchase.status = '3' # 全部入库
else: # 第二种情况: 小于采购总数量
item.purchase.status = '2' # 部分入库
item.purchase.save()
# 每一个入库单中货品的库存需要增加
for storage_item in item.item_list.all():
# 需要增加:原来的库存 += 当前入库数量
GoodsInventoryModel.objects \
.filter(goods_id=storage_item.goods_id, warehouse_id=storage_item.warehouse_id) \
.update(cur_inventory=F('cur_inventory') + storage_item.purchase_count)
# 修改审核状态
self.get_queryset().filter(id__in=audit_ids).update(status='1', check_user_name=check_user.real_name, check_user_id=check_user.id)
return Response(status=status.HTTP_200_OK)

@ -45,6 +45,7 @@ INSTALLED_APPS = [
'basic_info',
'goods_info',
'purchase_info',
'warehouse_info',
# 'django.contrib.staticfiles', # required for serving swagger ui's css/js files
'drf_yasg',

Loading…
Cancel
Save