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 = {'get': '*', 'post':'fifoitem_create', 'put':'fifoitem_update', 'delete':'fifoitem_delete'} 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) 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) 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) 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']