示例#1
0
class TokenObtainPairView(CoreTokenObtainPairView):
    """
    Takes a set of user credentials and returns an access and refresh JSON web
    token pair to prove the authentication of those credentials.
    """
    serializer_class = TokenObtainPairSerializer
    schema = CustomSchema()
示例#2
0
class UserListAPIView(ListAPIView):
    """
    List of existing agents
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    schema = CustomSchema()
示例#3
0
class RoleListAPIView(ListAPIView):
    """
    List of existing roles
    """
    queryset = Role.objects.all()
    serializer_class = RoleSerializer
    schema = CustomSchema()
示例#4
0
class PingAPIView(APIView):
    """
    Endpoint for checking connection with server. Returns 200 status and "OK".
    """
    schema = CustomSchema()

    def get(self, request, format=None):
        return Response("OK", status=status.HTTP_200_OK)
示例#5
0
class NotificationViewSet(ReadOnlyModelViewSet):
    serializer_class = NotificationSerializer
    schema = CustomSchema()

    def get_queryset(self):
        user = self.request.user
        queryset = Notification.objects.filter(users=user).exclude(
            read_by=user)
        user.read_notifications.add(*queryset)
        return queryset
示例#6
0
class RegistrationAPIView(GenericAPIView):
    permission_classes = (AllowAny, )
    serializer_class = RegistrationSerializer
    schema = CustomSchema()

    def post(self, request):
        serializer = self.serializer_class(data=request.data,
                                           context={'user': request.user})
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)
示例#7
0
class BaseAdditionalDataViewSet(object):
    schema = CustomSchema()
    filter_backends = (SearchFilter, )

    def get_queryset(self):
        if self.request.GET.get('active_only'):
            return self.model.objects.filter(active=True)
        return self.model.objects.all()

    def perform_destroy(self, instance):
        instance.active = False
        instance.save()

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid()
        if serializer.errors:
            if 'name' in serializer.errors:
                name_errors = serializer.errors['name']
                if len(name_errors) == 1 and name_errors[0].code == 'unique':
                    objects = self.model.objects.filter(
                        name=request.data['name'], active=False)
                    if objects.count():
                        objects.update(active=True)
                        raise ValidationError({
                            'name': [
                                ErrorDetail(
                                    f'{str(name_errors[0])} Object is set active again. Refresh the page to see the change.',
                                    name_errors[0].code)
                            ]
                        })
                    raise ValidationError(serializer.errors)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers=headers)
示例#8
0
class ReplantationViewSet(mixins.CreateModelMixin, mixins.ListModelMixin,
                          GenericViewSet):
    """
        Viewset API for Replantations
    """

    queryset = Replantation.objects.all().order_by('-id')
    pagination_class = LimitOffsetPagination
    schema = CustomSchema()

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context['request'] = self.request
        return context

    def get_serializer_class(self):
        if self.action == 'list':
            return ReplantationListSerializer
        return ReplantationSerializer

    def translate_year_to_timestamp_range(self, year):
        year_date = pytz.timezone(settings.TIME_ZONE).localize(
            datetime.strptime(str(year), '%Y'))
        return year_date.timestamp(), year_date.replace(month=12,
                                                        day=31).timestamp()

    def _filter_entities(self, request):
        year = request.GET.get('year')

        filter_q = Q()
        if year:
            from_timestamp, to_timestamp = self.translate_year_to_timestamp_range(
                year)
            filter_q |= Q(beginning_date__range=(from_timestamp, to_timestamp)) | \
                        Q(ending_date__range=(from_timestamp, to_timestamp))

        return filter_q

    def list(self, request, *args, **kwargs):
        """
        ---
        desc: List API for replantations
        ret: List of replantations
        input:
        -
            name: year
            required: false
            location: query
            type: number
        ---
        """
        filter_q = self._filter_entities(request)
        queryset = self.queryset.filter(filter_q).distinct()
        page = self.paginator.paginate_queryset(queryset=queryset,
                                                request=request)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.paginator.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    @action(methods=['get'], detail=False)
    def plots(self, request):
        """
        ---
        desc: List API for Packages without replantation and with Logging Ending step.
        ret: List of packages
        ---
        """
        queryset = Package.objects.filter(
            type=Package.PLOT,
            last_action__action=Entity.LOGGING_ENDING,
            replantation__isnull=True).distinct()
        page = self.paginator.paginate_queryset(queryset=queryset,
                                                request=request)
        if page is not None:
            serializer = PackagePidSerializer(page, many=True)
            return self.paginator.get_paginated_response(serializer.data)
        serializer = PackagePidSerializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)
示例#9
0
class PackageViewSet(ViewSet, MultiSerializerMixin):
    """
    Viewset for packages
    """
    lookup_field = 'pk'
    queryset = Package.objects.order_by('-id')
    pagination_class = LimitOffsetPagination
    schema = CustomSchema()
    serializer_class = PackagesSerializer
    custom_serializer_classes = {
        'get_package_details': PackageDetailsSerializer,
    }

    def _filter_entities(self, request, additional_filters={}):
        from_timestamp = request.GET.get('from_timestamp')
        to_timestamp = request.GET.get('to_timestamp')

        filter_kwargs = {}
        if from_timestamp and to_timestamp:
            filter_kwargs['package_entities__timestamp__range'] = (
                from_timestamp, to_timestamp)
        elif from_timestamp and not to_timestamp:
            filter_kwargs['package_entities__timestamp__gte'] = from_timestamp
        elif to_timestamp and not from_timestamp:
            filter_kwargs['package_entities__timestamp__lte'] = to_timestamp
        if request and 'keyword' in request.query_params and len(
                request.query_params['keyword']) > 0:
            filter_kwargs['pid__icontains'] = request.query_params['keyword']

        filter_kwargs = {**filter_kwargs, **additional_filters}

        return filter_kwargs

    def list(self, request):
        """
        ---
        desc: List API for packages
        ret: List of packages
        input:
        -
            name: type
            required: false
            location: query
            type: string
        ---
        """
        type = request.GET.get('type')
        filter_kwargs = self._filter_entities(request)
        if type and type.lower() != 'all':
            filter_kwargs['type'] = type.upper()
        queryset = self.queryset.filter(**filter_kwargs).exclude(
            last_action__action=Entity.INITIAL).distinct()
        page = self.paginator.paginate_queryset(queryset=queryset,
                                                request=request)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.paginator.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    @action(methods=['get'], detail=True)
    def get_package_details(self, request, pk=None):
        """
        ---
        desc: Details API for package
        ret: details for package by pk
        input:
        -
            name: id
            required: true
            location: path
            type: integer
        ---
        """
        package = get_object_or_404(Package, pk=pk)
        serializer = self.get_serializer(package)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def get_package_chain_queryset(self, pk):
        package = get_object_or_404(Package, pk=pk)
        return self.queryset.filter(
            Q(id=package.id) |  # matches self
            Q(plot=package) |  # matches harvest's plot
            Q(harvest=package) |  # matches truck's harvest
            Q(trucks=package) |  # matches harvest's trucks
            Q(plot_harvest=package) |  # matches plot's harvest
            Q(plot_harvest__trucks=package) |  # matches plot's trucks
            Q(harvest__plot=package) |  # matches truck's plot
            Q(harvest__trucks=package)  # matches truck's other trucks
        ).distinct().order_by('id')

    @action(methods=['get'], detail=True)
    def get_package_chain(self, request, pk=None):
        """
        ---
        desc: Chain of actions for package
        ret: Chain of actions for package
        input:
        -
            name: id
            required: true
            location: path
            type: integer
        ---
        """
        chain = self.get_serializer(self.get_package_chain_queryset(pk),
                                    many=True)
        return Response(chain.data, status=status.HTTP_200_OK)

    @action(methods=['post'], detail=True)
    def finalize_supply_chain(self, request, pk=None):
        """
        ---
        desc: Mark supply chain as complete
        ret: Chain of actions for package
        input:
        -
            name: id
            required: true
            location: path
            type: integer
        ---
        """
        queryset = self.get_package_chain_queryset(pk)
        queryset.update(is_finished=True)
        chain = self.get_serializer(self.get_package_chain_queryset(pk),
                                    many=True)
        return Response(chain.data, status=status.HTTP_200_OK)
示例#10
0
class EntityViewSet(ViewSet, MultiSerializerMixin):
    """
    Viewset for entities
    """
    lookup_field = 'pk'
    queryset = Entity.objects.all()
    pagination_class = LimitOffsetPagination
    schema = CustomSchema()
    serializer_class = EntityListSerializer
    custom_serializer_classes = {
        'new': EntitySerializer,
        'harvests': PackagePidSerializer,
    }

    @action(methods=['get'], detail=False)
    def types(self, request):
        """
        ---
        desc: GET endpoint for list of possible actions
        ret: dict with actions. Key - short name, Value - full name.
        ---
        """
        return Response({i[0]: i[1]
                         for i in Entity.ACTIONS},
                        status=status.HTTP_200_OK)

    @action(methods=['post'], detail=False)
    def new(self, request, pk=None):
        """
        ---
        desc: POST for creating new action
        ret: package pid
        input:
        -
            name: action
            required: true
            location: form
            type: string
        -
            name: pid
            required: false
            location: form
            type: string
        -
            name: timestamp
            required: true
            location: form
            type: integer
        -
            name: properties
            required: true
            location: form
            type: object
        -
            name: documents_photos/receipt_photos
            required: false
            location: form
            type: image
        -
            name: location
            required: true
            location: form
            type: object
        ---
        """
        ser = self.get_serializer(data=request.data,
                                  context={'request': request})
        ser.is_valid(raise_exception=True)
        ser.save()
        return Response(
            {
                'pid': ser.instance.package.pid,
                'package_id': ser.instance.package_id,
                'timestamp': ser.instance.timestamp
            },
            status=status.HTTP_200_OK)

    @action(methods=['get'], detail=False)
    def plots(self, request):
        """
        ---
        desc: List API plots with defined action code
        ret: List of plot actions
        input:
        -
            name: last_action
            required: true
            location: query
            type: string
        ---
        """
        last_action = request.GET.get('last_action')
        queryset = Package.objects.filter(
            type=Package.PLOT,
            package_entities__user=request.user,
            last_action__action=last_action,
            plot_harvest__isnull=True).distinct()
        page = self.paginator.paginate_queryset(queryset=queryset,
                                                request=request)
        if page is not None:
            serializer = PackagePidSerializer(page, many=True)
            return self.paginator.get_paginated_response(serializer.data)
        serializer = PackagePidSerializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    @action(methods=['get'], detail=False)
    def harvests(self, request):
        """
        ---
        desc: List API harvests with defined action code
        ret: List of harvests actions
        input:
        -
            name: last_action
            required: true
            location: query
            type: string
        ---
        """
        last_action = request.GET.get('last_action')
        queryset = Package.objects.filter(
            type=Package.HARVEST,
            package_entities__user=request.user,
            last_action__action=last_action).distinct()
        page = self.paginator.paginate_queryset(queryset=queryset,
                                                request=request)
        if page is not None:
            serializer = PackagePidSerializer(page, many=True)
            return self.paginator.get_paginated_response(serializer.data)
        serializer = PackagePidSerializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    @action(methods=['get'], detail=False)
    def ovens(self, request):
        """
        ---
        desc: List API active ovens for given harvest
        ret: List of ovens
        input:
        -
            name: harvest_id
            required: true
            location: query
            type: string
        ---
        """
        harvest_id = request.GET.get('harvest_id')
        queryset = Oven.objects.filter(
            carbonization_beginning__entity__package_id=harvest_id,
            carbonization_beginning__entity__user=request.user,
            carbonization_ending__isnull=True).distinct()
        page = self.paginator.paginate_queryset(queryset=queryset,
                                                request=request)
        if page is not None:
            serializer = OvenSimpleSerializer(page, many=True)
            return self.paginator.get_paginated_response(serializer.data)
        serializer = OvenSimpleSerializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def _filter_entities(self, request, additional_filters={}):
        from_timestamp = request.GET.get('from_timestamp')
        to_timestamp = request.GET.get('to_timestamp')

        filter_kwargs = {}
        if from_timestamp and to_timestamp:
            filter_kwargs['timestamp__range'] = (from_timestamp, to_timestamp)
        elif from_timestamp and not to_timestamp:
            filter_kwargs['timestamp__gte'] = from_timestamp
        elif to_timestamp and not from_timestamp:
            filter_kwargs['timestamp__lte'] = to_timestamp
        if request and 'keyword' in request.query_params and len(
                request.query_params['keyword']) > 0:
            filter_kwargs['package__pid__icontains'] = request.query_params[
                'keyword']
        if request and 'types' in request.query_params and len(
                request.query_params['types']) > 0:
            filter_kwargs['package__type__in'] = [
                t.upper() for t in request.query_params['types'].split(',')
            ]
        filter_kwargs = {**filter_kwargs, **additional_filters}

        return filter_kwargs

    def list(self, request, *args, **kwargs):
        """
        ---
        desc: List API for actions.
        ret: List of entities with pids and action types only
        input:
        -
            name: from_timestamp
            required: false
            location: query
            type: integer
        -
            name: to_timestamp
            required: false
            location: query
            type: integer
        -
            name: keyword
            required: false
            location: query
        -
            name: limit
            required: false
            location: query
            type: integer
        -
            name: offset
            required: false
            location: query
            type: integer
        """
        filter_kwargs = self._filter_entities(request)
        entities = self.queryset.filter(**filter_kwargs)
        ser = self.serializer_class(entities, many=True)
        paginator = self.pagination_class()
        page = paginator.paginate_queryset(queryset=ser.data, request=request)
        if page is not None:
            return paginator.get_paginated_response(page)
        return Response(ser.data, status=status.HTTP_200_OK)

    @action(methods=['get'], detail=False)
    def dots(self, request):
        dates = json.loads(request.query_params.get('dates', None))
        response = {}
        for timestamp in dates:
            start_timestamp = int(timestamp)
            end_timestamp = start_timestamp + 24 * 60 * 60 - 1  # -1 to cover midnight edgecase
            available_actions = list(
                Package.objects.filter(package_entities__timestamp__range=(
                    start_timestamp,
                    end_timestamp)).values_list('type').distinct())
            response[start_timestamp] = available_actions
        return Response(response, status=status.HTTP_200_OK)
示例#11
0
from django.urls import path

from rest_framework_simplejwt import views as jwt_views
from apps.api.v1.users.views import RegistrationAPIView, RoleListAPIView, UserListAPIView, TokenObtainPairView
from config.swagger_schema import CustomSchema

app_name = 'users'

urlpatterns = [
    path('login/', TokenObtainPairView.as_view(), name='login-view'),
    path('token-refresh/', jwt_views.TokenRefreshView.as_view(**{'schema': CustomSchema()}), name='token_refresh'),
    path('register/', RegistrationAPIView.as_view(), name='register'),
    path('roles/', RoleListAPIView.as_view(), name='roles'),
    path('agents/', UserListAPIView.as_view(), name='agents'),
]