|
|
|
@ -0,0 +1,197 @@
|
|
|
|
|
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)
|