238 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
| from rest_framework import serializers
 | |
| from rest_framework import exceptions
 | |
| from rest_framework.exceptions import APIException, ValidationError
 | |
| from rest_framework.mixins import DestroyModelMixin, ListModelMixin, UpdateModelMixin, CreateModelMixin
 | |
| from rest_framework.viewsets import GenericViewSet, ModelViewSet
 | |
| from apps.inm.filters import IProductFilterSet, MbFilterSet
 | |
| 
 | |
| from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse, Inventory
 | |
| from apps.inm.serializers import FIFOInOtherSerializer, FIFOItemCreateSerializer, FIFOItemSerializer, FIFOInPurSerializer, FIFOItemUpdateSerializer, FIFOListSerializer, FIFOOutOtherSerializer, IProductListSerializer, \
 | |
|     InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, \
 | |
|     WareHouseCreateUpdateSerializer, InventorySerializer
 | |
| from apps.inm.services import InmService
 | |
| from apps.qm.models import TestRecordItem
 | |
| from apps.system.mixins import CreateUpdateModelAMixin
 | |
| from rest_framework.decorators import action
 | |
| from rest_framework.response import Response
 | |
| from django.db import transaction
 | |
| from django.utils import timezone
 | |
| 
 | |
| 
 | |
| # Create your views here.
 | |
| 
 | |
| 
 | |
| class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet):
 | |
|     """
 | |
|     仓库-增删改查
 | |
|     """
 | |
|     perms_map = {'get': '*', 'post':'warehouse_create', 
 | |
|                 'put':'warehouse_update', 'delete':'warehouse_delete'}
 | |
|     queryset = WareHouse.objects.select_related('create_by').all()
 | |
|     serializer_class = WareHouseSerializer
 | |
|     search_fields = ['name', 'number', 'place']
 | |
|     filterset_fields = []
 | |
|     ordering_fields = ['create_time']
 | |
|     ordering = ['-create_time']
 | |
| 
 | |
|     def get_serializer_class(self):
 | |
|         if self.action in ['create', 'update']:
 | |
|             return WareHouseCreateUpdateSerializer
 | |
|         return WareHouseSerializer
 | |
| 
 | |
| 
 | |
| class InventoryViewSet(ListModelMixin, GenericViewSet):
 | |
|     """
 | |
|     仓库物料表
 | |
|     """
 | |
|     perms_map = {'get': '*'}
 | |
|     queryset = Inventory.objects.select_related(
 | |
|         'material', 'warehouse').filter(count__gt=0).all()
 | |
|     serializer_class = InventorySerializer
 | |
|     filterset_fields = ['material', 'warehouse']
 | |
|     search_fields = []
 | |
|     ordering_fields = ['create_time']
 | |
|     ordering = ['-create_time']
 | |
| 
 | |
| 
 | |
| class MaterialBatchViewSet(ListModelMixin, GenericViewSet):
 | |
|     perms_map = {'get': '*'}
 | |
|     queryset = MaterialBatch.objects.select_related(
 | |
|         'material', 'warehouse').filter(count__gt=0).all()
 | |
|     serializer_class = MaterialBatchSerializer
 | |
|     # filterset_fields = ['material', 'warehouse']
 | |
|     filterset_class = MbFilterSet
 | |
|     search_fields = []
 | |
|     ordering_fields = ['create_time']
 | |
|     ordering = ['-create_time']
 | |
| 
 | |
|     @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=MaterialBatchQuerySerializer)
 | |
|     def query(self, request, pk=None):
 | |
|         """
 | |
|         复杂查询
 | |
|         """
 | |
|         data = request.data
 | |
|         serializer = MaterialBatchQuerySerializer(data=data)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         queryset = self.queryset.filter(
 | |
|             warehouse__id=data['warehouse'], material__id__in=data['materials'])
 | |
|         return Response(MaterialBatchSerializer(instance=queryset, many=True).data)
 | |
| 
 | |
| 
 | |
| class FIFOItemViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
 | |
|     """
 | |
|     出入库记录详情表
 | |
|     """
 | |
|     perms_map = {'*':'*'}
 | |
|     queryset = FIFOItem.objects.select_related('material', 'fifo').prefetch_related('files').all()
 | |
|     serializer_class = FIFOItemSerializer
 | |
|     filterset_fields = ['material', 'fifo',
 | |
|                         'fifo__type', 'need_test', 'is_testok']
 | |
|     search_fields = []
 | |
|     ordering_fields = ['create_time']
 | |
|     ordering = ['-create_time']
 | |
| 
 | |
|     def get_serializer_class(self):
 | |
|         if self.action == 'update':
 | |
|             return FIFOItemUpdateSerializer
 | |
|         elif self.action == 'create':
 | |
|             return FIFOItemCreateSerializer
 | |
|         return super().get_serializer_class()
 | |
| 
 | |
|     def update(self, request, *args, **kwargs):
 | |
|         obj = self.get_object()
 | |
|         if obj.fifo.is_audited:
 | |
|             raise ValidationError('该出入库记录已审核')
 | |
|         return super().update(request, *args, **kwargs)
 | |
| 
 | |
|     def destroy(self, request, *args, **kwargs):
 | |
|         obj = self.get_object()
 | |
|         if obj.fifo.is_audited:
 | |
|             raise ValidationError('该出入库记录已审核')
 | |
|         return super().destroy(request, *args, **kwargs)
 | |
| 
 | |
|     @action(methods=['post'], detail=False, perms_map={'post': 'fifoitem_test'}, serializer_class=InmTestRecordCreateSerializer)
 | |
|     def test(self, request, pk=None):
 | |
|         """
 | |
|         检验
 | |
|         """
 | |
|         serializer = InmTestRecordCreateSerializer(data=request.data)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         vdata = serializer.validated_data
 | |
|         record_data = vdata.pop('record_data')
 | |
|         if 'is_testok' not in vdata:
 | |
|             raise APIException('未填写检验结论')
 | |
|         with transaction.atomic():
 | |
|             obj = serializer.save(create_by=self.request.user)
 | |
|             tris = []
 | |
|             for m in record_data:  # 保存记录详情
 | |
|                 m['field_value'] = m['field_value']
 | |
|                 m['is_testok'] = m['is_testok'] if 'is_testok' in m else True
 | |
|                 m['test_record'] = obj
 | |
|                 tris.append(TestRecordItem(**m))
 | |
|             TestRecordItem.objects.bulk_create(tris)
 | |
| 
 | |
|             # 如果检验合格
 | |
|             if obj.fifo_item:
 | |
|                 obj.fifo_item.is_testok = True if obj.is_testok else False
 | |
|                 obj.fifo_item.save()
 | |
|         return Response()
 | |
| 
 | |
| 
 | |
| class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
 | |
|     """
 | |
|     出入库记录
 | |
|     """
 | |
|     perms_map = {'get': '*', 'delete':'fifo_delete'}
 | |
|     queryset = FIFO.objects.select_related('auditor', 'create_by')
 | |
|     serializer_class = FIFOListSerializer
 | |
|     filterset_fields = '__all__'
 | |
|     ordering_fields = '__all__'
 | |
|     search_fields = []
 | |
|     ordering = ['-pk']
 | |
| 
 | |
|     def get_serializer_class(self):
 | |
|         if self.action == 'list':
 | |
|             return FIFOListSerializer
 | |
|         return super().get_serializer_class()
 | |
| 
 | |
|     def destroy(self, request, *args, **kwargs):
 | |
|         obj = self.get_object()
 | |
|         if obj.is_audited:
 | |
|             raise exceptions.APIException('该记录已审核,不可删除')
 | |
|         return super().destroy(request, *args, **kwargs)
 | |
| 
 | |
|     @action(methods=['post'], detail=False, perms_map={'post': 'fifo_in_pur'}, serializer_class=FIFOInPurSerializer)
 | |
|     @transaction.atomic()
 | |
|     def in_pur(self, request, pk=None):
 | |
|         """
 | |
|         采购入库
 | |
|         """
 | |
|         serializer = self.get_serializer(data=request.data)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         serializer.save(create_by=request.user)
 | |
|         return Response()
 | |
|     
 | |
|     @action(methods=['post'], detail=False, perms_map={'post': 'fifo_in_other'}, 
 | |
|         serializer_class=FIFOInOtherSerializer)
 | |
|     @transaction.atomic()
 | |
|     def in_other(self, request, pk=None):
 | |
|         """
 | |
|         其他入库
 | |
|         """
 | |
|         serializer = self.get_serializer(data=request.data)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         serializer.save(create_by=request.user)
 | |
|         return Response()
 | |
| 
 | |
|     @action(methods=['post'], detail=False, perms_map={'post': 'fifo_out_other'}, 
 | |
|         serializer_class=FIFOOutOtherSerializer)
 | |
|     @transaction.atomic()
 | |
|     def out_other(self, request, pk=None):
 | |
|         """
 | |
|         其他出库
 | |
|         """
 | |
|         serializer = self.get_serializer(data=request.data)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         serializer.save(create_by=request.user)
 | |
|         return Response()
 | |
| 
 | |
|     @action(methods=['post'], detail=True, perms_map={'post': 'fifo_audit'}, serializer_class=serializers.Serializer)
 | |
|     @transaction.atomic
 | |
|     def audit(self, request, pk=None):
 | |
|         """
 | |
|         审核通过
 | |
|         """
 | |
|         obj = self.get_object()
 | |
|         if obj.is_audited:
 | |
|                 raise APIException('该入库记录已审核通过')
 | |
|         if obj.type == FIFO.FIFO_TYPE_SALE_OUT: # 如果是销售提货,需额外处理
 | |
|             InmService.sale_out_audit(obj)
 | |
|         else:
 | |
|             if not FIFOItem.objects.filter(fifo=obj).exists():
 | |
|                 raise ValidationError('出入库条目为空')
 | |
|             for i in FIFOItem.objects.filter(fifo=obj, need_test=True):
 | |
|                 if not i.is_testok:
 | |
|                     raise APIException('未检验通过, 不可审核')
 | |
|         obj.is_audited = True
 | |
|         obj.auditor = request.user
 | |
|         obj.inout_date = timezone.now()  # 也是审核日期
 | |
|         obj.save()
 | |
|         InmService.update_inm(obj)  # 更新库存
 | |
|         return Response()
 | |
| 
 | |
| 
 | |
| class IProductViewSet(ListModelMixin, GenericViewSet):
 | |
|     """
 | |
|     半成品库存表
 | |
|     """
 | |
|     perms_map = {'get': '*'}
 | |
|     queryset = IProduct.objects.select_related(
 | |
|         'material', 'warehouse', 
 | |
|         'wproduct__subproduction_plan__production_plan__order',
 | |
|         'wproduct__to_order')
 | |
|     serializer_class = IProductListSerializer
 | |
|     filterset_class = IProductFilterSet
 | |
|     search_fields = []
 | |
|     ordering_fields = ['create_time']
 | |
|     ordering = ['-create_time']
 |