You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
10 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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 SettlementAccountModel, CustomerModel
from erp_system.models import UserModel
from financial_info.models import ReceiptModel, ReceiptItemModel
from financial_info.serializer.receipt_serializer import ReceiptSerializer
from warehouse_info.models import SaleDeliverModel
class ReceiptViewSet(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: 修改后的收款单信息
list:
收款单--该接口可以弃用
收款单列表信息, status: 200(成功), return: 收款单信息列表
retrieve:
查询某一个收款单
查询指定ID的收款单, status: 200(成功), return: 用户收款单
"""
queryset = ReceiptModel.objects.all()
serializer_class = ReceiptSerializer
pagination_class = GlobalPagination
def get_queryset(self):
if self.action == 'find': # 过滤查询
# 获取请求参数(在json中)
number_code = self.request.data.get('number_code', None)
check_user = self.request.data.get('check_user', 0)
start_date = self.request.data.get('start_date', None)
end_date = self.request.data.get('start_date', None)
customer = self.request.data.get('customer', 0)
operator_user = self.request.data.get('operator_user', 0)
status = self.request.data.get('status', None)
account = self.request.data.get('account', 0)
sale_number_code = self.request.data.get('sale_number_code', None)
query = Q()
if check_user:
query.add(Q(check_user__id=check_user), 'AND')
if account:
query.add(Q(account__id=account), 'AND')
if sale_number_code:
query.add(Q(sale__number_code__contains=sale_number_code), 'AND')
if start_date:
query.add(Q(pay_date__gt=start_date), 'AND')
if end_date:
query.add(Q(pay_date__lt=end_date), 'AND')
if customer:
query.add(Q(customer__id=customer), '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 ReceiptModel.objects.filter(query).distinct().all()
else:
return ReceiptModel.objects.all()
params = openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'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"),
'customer': openapi.Schema(type=openapi.TYPE_INTEGER, description="客户的ID"),
'operator_user': openapi.Schema(type=openapi.TYPE_INTEGER, description="财务人员的ID"),
'check_user': openapi.Schema(type=openapi.TYPE_INTEGER, description="审核人员的ID"),
'account': openapi.Schema(type=openapi.TYPE_INTEGER, description="结算账户的ID"),
'sale_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(ReceiptViewSet, 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"),
})
@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 receipt in queryset: # 期中receipt是收款单
# 判断1关联的销售 单状态是否为“未审核”
if receipt.sale and receipt.sale.status == '0':
return Response(data={'detail': '销售订单未审核,不能收款'}, status=status.HTTP_400_BAD_REQUEST)
# 判断2 收款单的状态是否为:“已审核”
if receipt.status == '1':
return Response(data={'detail': '收款单已经审核,不需要再次审核'}, status=status.HTTP_400_BAD_REQUEST)
# 处理关联业务逻辑
# 业务一: 销售定金收款
if receipt.receipt_category == '1' and receipt.sale and not receipt.item_list.exists():
receipt.sale.status = '5' # 已收 销售定金
receipt.sale.save()
# 业务二: 客户还款 的收款
if receipt.receipt_category == '3' and not receipt.item_list.exists():
CustomerModel.objects.filter(id=receipt.customer.id).update(
current_receivable=F('current_receivable') - receipt.this_money)
# 业务三: 出库货款 的收入
if receipt.receipt_category == '2' and receipt.sale:
if receipt.item_list.exists(): # 这种判断不回从数据库中返回数据
for item in receipt.item_list.all(): # 期中item是收款项目
# 判断4 出库单必须是已经审核状态
if item.deliver_storage and item.deliver_storage.status != '1':
return Response(data={'detail': '出库单未审核或者已经收款,不能收款'},
status=status.HTTP_400_BAD_REQUEST)
# 业务三——第1种情况 对应的出库单,是否应该:收款完成 ,首先需要查询该出库单的已经收款金额之和
sum_dict = ReceiptItemModel.objects \
.filter(deliver_storage_id=item.deliver_storage.id, receipt__status='1') \
.aggregate(sum=Sum('this_money'))
in_sum = sum_dict['sum'] if sum_dict['sum'] else 0
if item.should_money == (in_sum + item.this_money):
item.deliver_storage.status = '2' # 把出库单的状态修改为:收款完成
item.deliver_storage.save()
# 业务三——第2种情况 对应的销售单状态是否要改为:销售完成
# 销售完成的条件: 1、该销售单必须是全部出库状态2、该销售单中 所有的出库单状态也都必须是:收款完成
sale = item.receipt.sale
if sale.status == '3':
# 查询 该销售单中 所有出库单状态不是:'收款完成' 的有多少个?
number = SaleDeliverModel.objects \
.filter(sale_id=sale.id) \
.exclude(status='2').count()
if number == 0: # 则 所有的出库单状态都为:收款完成
sale.status = '4' # 修改销售单状态为: 销售完成
sale.save()
else:
return Response(data={'detail': '没有选择收款项目,支收货款的时候必须选择'},
status=status.HTTP_400_BAD_REQUEST)
# 至此: 三种业务都完成
# 业务四: 修改 结算账户的余额
SettlementAccountModel.objects.filter(id=receipt.account.id) \
.update(balance=F('balance') + receipt.this_money)
# 至此: 四种业务都完成,开始修改收款单的状态以及审核信息
# 审核
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)