210 lines
7.9 KiB
Python
210 lines
7.9 KiB
Python
from django.db import transaction
|
|
from django.db.models.aggregates import Count
|
|
from rest_framework import exceptions, serializers
|
|
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin
|
|
from apps.mtm.models import Material
|
|
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
|
|
from apps.inm.signals import update_inm
|
|
from apps.sam.serializers import ContractCreateUpdateSerializer, ContractSerializer, CustomerCreateUpdateSerializer, CustomerSerializer, OrderCreateUpdateSerializer, OrderSerializer, SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer
|
|
from apps.sam.models import Contract, Customer, Order, Sale, SaleProduct
|
|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
|
from apps.system.mixins import CreateUpdateCustomMixin
|
|
from django.shortcuts import render
|
|
from rest_framework.decorators import action
|
|
from django.db.models import F
|
|
from rest_framework.response import Response
|
|
from django.utils import timezone
|
|
# Create your views here.
|
|
class CustomerViewSet(CreateUpdateCustomMixin, ModelViewSet):
|
|
"""
|
|
客户-增删改查
|
|
"""
|
|
perms_map = {'*': '*'}
|
|
queryset = Customer.objects.all()
|
|
serializer_class = CustomerSerializer
|
|
search_fields = ['name', 'contact']
|
|
filterset_fields = []
|
|
ordering_fields = ['create_time']
|
|
ordering = ['-create_time']
|
|
|
|
def get_serializer_class(self):
|
|
if self.action in ['create', 'update']:
|
|
return CustomerCreateUpdateSerializer
|
|
return CustomerSerializer
|
|
|
|
|
|
class ContractViewSet(CreateUpdateCustomMixin, ModelViewSet):
|
|
"""
|
|
合同-增删改查
|
|
"""
|
|
perms_map = {'*': '*'}
|
|
queryset = Contract.objects.select_related('customer').all()
|
|
serializer_class = ContractSerializer
|
|
search_fields = ['name']
|
|
filterset_fields = []
|
|
ordering_fields = ['create_time']
|
|
ordering = ['-create_time']
|
|
|
|
def get_serializer_class(self):
|
|
if self.action in ['create', 'update']:
|
|
return ContractCreateUpdateSerializer
|
|
return ContractSerializer
|
|
|
|
class OrderViewSet(CreateUpdateCustomMixin, ModelViewSet):
|
|
"""
|
|
订单-增删改查
|
|
"""
|
|
perms_map = {'*': '*'}
|
|
queryset = Order.objects.select_related('contract', 'customer').all()
|
|
serializer_class = OrderSerializer
|
|
search_fields = ['number', 'product']
|
|
filterset_fields = ['product', 'contract', 'customer']
|
|
ordering_fields = ['create_time']
|
|
ordering = ['-create_time']
|
|
|
|
def get_serializer_class(self):
|
|
if self.action in ['create', 'update']:
|
|
return OrderCreateUpdateSerializer
|
|
return super().get_serializer_class()
|
|
|
|
@action(methods=['get'], detail=False, perms_map={'get':'*'})
|
|
def toplan(self, request, pk=None):
|
|
queryset = Order.objects.filter(count__gt=F('planed_count')).order_by('-id')
|
|
page = self.paginate_queryset(queryset)
|
|
if page is not None:
|
|
serializer = self.get_serializer(page, many=True)
|
|
return self.get_paginated_response(serializer.data)
|
|
serializer = self.get_serializer(queryset, many=True)
|
|
return Response(serializer.data)
|
|
|
|
|
|
class SaleViewSet(CreateUpdateCustomMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
|
|
"""
|
|
销售记录
|
|
"""
|
|
perms_map = {'*': '*'}
|
|
queryset = Sale.objects.select_related('customer', 'order', 'product', 'order__contract').all()
|
|
serializer_class = SaleListSerializer
|
|
search_fields = ['customer__name', 'order__number']
|
|
filterset_fields = ['product', 'order', 'customer']
|
|
ordering_fields = ['create_time']
|
|
ordering = ['-create_time']
|
|
|
|
def get_serializer_class(self):
|
|
if self.action == 'create':
|
|
return SaleCreateSerializer
|
|
elif self.action == 'retrieve':
|
|
return SaleListSerializer
|
|
return super().get_serializer_class()
|
|
|
|
def create(self, request, *args, **kwargs):
|
|
data = request.data
|
|
serializer = SaleCreateSerializer(data=data)
|
|
serializer.is_valid(raise_exception=True)
|
|
vdata = serializer.validated_data
|
|
with transaction.atomic():
|
|
iproducts = vdata.pop('iproducts')
|
|
vdata['count'] = len(iproducts)
|
|
sale = Sale.objects.create(**vdata)
|
|
i_l = []
|
|
for i in iproducts:
|
|
i_d ={}
|
|
i_d['sale'] = sale
|
|
i_d['number'] = i.number
|
|
i_d['iproduct'] = i
|
|
i_l.append(SaleProduct(**i_d))
|
|
SaleProduct.objects.bulk_create(i_l)
|
|
return Response()
|
|
|
|
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer)
|
|
@transaction.atomic
|
|
def audit(self, request, pk=None):
|
|
"""
|
|
审核
|
|
"""
|
|
obj = self.get_object()
|
|
if obj.is_audited:
|
|
raise exceptions.APIException('已审核通过')
|
|
# 创建出库记录
|
|
fifo = FIFO()
|
|
fifo.type = FIFO.FIFO_TYPE_SALE_OUT
|
|
fifo.is_audited = True
|
|
fifo.auditor = request.user
|
|
fifo.inout_date = timezone.now()
|
|
fifo.create_by = request.user
|
|
fifo.save()
|
|
# 出库条目 暂时不校验是否军检
|
|
# spds = SaleProduct.objects.filter(sale=obj)
|
|
# for i in spds:
|
|
# if i.is_mtested and i.is_mtestok:
|
|
# pass
|
|
# else:
|
|
# raise exceptions.APIException('存在未军检产品')
|
|
# 创建出库条目
|
|
ips = IProduct.objects.filter(sale_iproduct__sale=obj)
|
|
items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id'))
|
|
for i in items:
|
|
warehouse = WareHouse.objects.get(id=i['warehouse'])
|
|
material = Material.objects.get(id=i['material'])
|
|
fifoitem = FIFOItem()
|
|
fifoitem.is_tested = True
|
|
fifoitem.is_testok = True
|
|
fifoitem.warehouse = warehouse
|
|
fifoitem.material = material
|
|
fifoitem.count = i['total']
|
|
fifoitem.batch = i['batch']
|
|
fifoitem.fifo = fifo
|
|
fifoitem.save()
|
|
items_p = ips.filter(warehouse=warehouse, batch=i['batch'])
|
|
ipxs = []
|
|
for i in items_p:
|
|
# 创建出库明细半成品
|
|
ip = {}
|
|
ip['fifoitem'] = fifoitem
|
|
ip['number'] = i.number
|
|
ip['material'] = i.material
|
|
ip['iproduct'] = i
|
|
ipxs.append(FIFOItemProduct(**ip))
|
|
FIFOItemProduct.objects.bulk_create(ipxs)
|
|
# 更新成品库情况
|
|
ips.update(is_saled=True)
|
|
# 更新库存
|
|
update_inm(fifo)
|
|
# 变更审核状态
|
|
obj.is_audited = True
|
|
obj.save()
|
|
# 变更订单状态
|
|
if obj.order:
|
|
order = obj.order
|
|
order.delivered_count = order.delivered_count + obj.count
|
|
order.save()
|
|
return Response()
|
|
|
|
class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, GenericViewSet):
|
|
"""
|
|
销售记录关联产品
|
|
"""
|
|
perms_map = {'*': '*'}
|
|
queryset = SaleProduct.objects.select_related('iproduct', 'iproduct__material', 'iproduct__warehouse').all()
|
|
serializer_class = SaleProductListSerializer
|
|
search_fields = []
|
|
filterset_fields = ['sale', 'iproduct']
|
|
ordering_fields = ['create_time']
|
|
ordering = ['id']
|
|
|
|
def get_serializer_class(self):
|
|
if self.action == 'create':
|
|
return SaleProductCreateSerializer
|
|
return super().get_serializer_class()
|
|
|
|
def destroy(self, request, *args, **kwargs):
|
|
obj = self.get_object()
|
|
sale = obj.sale
|
|
if sale.is_audited:
|
|
raise exceptions.APIException('该销售记录已审核,不可删除产品')
|
|
sale.count = SaleProduct.objects.filter(sale=obj.sale).count()
|
|
sale.save()
|
|
obj.delete()
|
|
return Response()
|
|
|
|
|