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.

196 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 SupplierModel, SettlementAccountModel
from erp_system.models import UserModel
from financial_info.models import PaymentModel, PaymentItemModel
from financial_info.serializer.payment_serializer import PaymentSerializer
from warehouse_info.models import PurchaseStorageModel
class PaymentViewSet(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 = PaymentModel.objects.all()
serializer_class = PaymentSerializer
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)
supplier = self.request.data.get('supplier', 0)
operator_user = self.request.data.get('operator_user', 0)
status = self.request.data.get('status', None)
account = self.request.data.get('account', 0)
purchase_number_code = self.request.data.get('purchase_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 purchase_number_code:
query.add(Q(purchase__number_code__contains=purchase_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 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 PaymentModel.objects.filter(query).distinct().all()
else:
return PaymentModel.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"),
'supplier': 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"),
'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(PaymentViewSet, 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 pm in queryset: # 期中pm是付款单
# 判断1关联的采购单状态是否为“未审核”
if pm.purchase and pm.purchase.status == '0':
return Response(data={'detail': '采购订单未审核,不能付款'}, status=status.HTTP_400_BAD_REQUEST)
# 判断2 付款单的状态是否为:“已审核”
if pm.status == '1':
return Response(data={'detail': '付款单已经审核,不需要再次审核'}, status=status.HTTP_400_BAD_REQUEST)
# 判断3 结算账户的余额是否够用
if pm.this_money > pm.account.balance:
return Response(data={'detail': '选择的结算账户中的余额不够,不能付款'}, status=status.HTTP_400_BAD_REQUEST)
# 处理关联业务逻辑
# 业务一: 采购定金付款
if pm.pay_category == '1' and pm.purchase and not pm.item_list.exists():
pm.purchase.status = '5' # 已付定金
pm.purchase.save()
# 业务二: 供应商欠款 支付
if pm.pay_category == '3' and not pm.item_list.exists():
SupplierModel.objects.filter(id=pm.supplier.id).update(current_pay=F('current_pay') - pm.pay_money)
# 业务三: 入库货款 支付
if pm.pay_category == '2' and pm.purchase:
if pm.item_list.exists(): # 这种判断不回从数据库中返回数据
for item in pm.item_list.all(): # 期中item是付款项目
# 判断4 入库单必须是已经审核状态
if item.purchase_storage and item.purchase_storage.status != '1':
return Response(data={'detail': '入库单未审核或者已经付款,不能付款'}, status=status.HTTP_400_BAD_REQUEST)
# 业务三——第1种情况 对应的入库单,是否应该:付款完成 ,首先需要查询该入库单的已经付款金额之和
sum_dict = PaymentItemModel.objects\
.filter(purchase_storage_id=item.purchase_storage.id, payment__status='1')\
.aggregate(sum=Sum('this_money'))
pay_sum = sum_dict['sum'] if sum_dict['sum'] else 0
if item.should_money == (pay_sum + item.this_money):
item.purchase_storage.status = '2' # 把入库单的状态修改为:付款完成
item.purchase_storage.save()
# 业务三——第2种情况 对应的采购单状态是否要改为:采购完成
# 采购完成的条件: 1、该采购单必须是全部入库状态2、该采购单中 所有的入库单状态也都必须是:付款完成
purchase = item.payment.purchase
if purchase.status == '3':
# 查询 该采购单中 所有入库单状态不是:'付款完成' 的有多少个?
number = PurchaseStorageModel.objects\
.filter(purchase_id=purchase.id)\
.exclude(status='2').count()
if number == 0: # 则 所有的入库单状态都为:付款完成
purchase.status = '4' # 修改采购单状态为: 采购完成
purchase.save()
else:
return Response(data={'detail': '没有选择付款项目,支付货款的时候必须选择'}, status=status.HTTP_400_BAD_REQUEST)
# 至此: 三种业务都完成
# 业务四: 修改 结算账户的余额
SettlementAccountModel.objects.filter(id=pm.account.id)\
.update(balance=F('balance') - pm.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)