forked from erp-dev/erp
fin
This commit is contained in:
@@ -27,6 +27,8 @@ from .mission import (
|
||||
MissionCategoryListCreateView,
|
||||
MissionDetailView,
|
||||
MissionListCreateView,
|
||||
MissionMyStatusCountsView,
|
||||
MissionMyView,
|
||||
MissionReopenView,
|
||||
MissionReplyListCreateView,
|
||||
MissionReplyRejectView,
|
||||
@@ -79,6 +81,8 @@ __all__ = [
|
||||
'MissionCategoryListCreateView',
|
||||
'MissionDetailView',
|
||||
'MissionListCreateView',
|
||||
'MissionMyStatusCountsView',
|
||||
'MissionMyView',
|
||||
'MissionReopenView',
|
||||
'MissionReplyListCreateView',
|
||||
'MissionReplyRejectView',
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
from datetime import datetime, time, timedelta
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.cache import cache
|
||||
from django.db import IntegrityError
|
||||
from django.db.models import Exists, OuterRef, Prefetch, Q
|
||||
from django.db.models import Count, Exists, OuterRef, Prefetch, Q
|
||||
from django.db.models import ProtectedError
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils import timezone
|
||||
from django.utils.dateparse import parse_date, parse_datetime
|
||||
from drf_spectacular.utils import extend_schema
|
||||
from rest_framework import permissions, serializers, status
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from flower.viewsets import LimitedLimitOffsetPagination
|
||||
from mission import models as mission_models
|
||||
from mission import services as mission_services
|
||||
|
||||
@@ -47,6 +53,11 @@ class MissionWriteSerializer(serializers.Serializer):
|
||||
required=False,
|
||||
allow_empty=True,
|
||||
)
|
||||
employee_type_ids = serializers.ListField(
|
||||
child=serializers.IntegerField(min_value=1),
|
||||
required=False,
|
||||
allow_empty=True,
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.is_create = kwargs.pop("is_create", False)
|
||||
@@ -358,6 +369,27 @@ def _parse_bool_query_param(request, param_name: str, default: bool) -> bool:
|
||||
raise serializers.ValidationError({param_name: "必须是布尔值"})
|
||||
|
||||
|
||||
def _parse_date_or_datetime_query_param(value: str | None) -> tuple[datetime | None, bool]:
|
||||
raw_value = (value or "").strip()
|
||||
if not raw_value:
|
||||
return None, False
|
||||
|
||||
tz = timezone.get_current_timezone()
|
||||
date_value = parse_date(raw_value)
|
||||
if date_value is not None:
|
||||
return timezone.make_aware(datetime.combine(date_value, time.min), tz), False
|
||||
|
||||
datetime_value = parse_datetime(raw_value)
|
||||
if datetime_value is not None:
|
||||
if timezone.is_naive(datetime_value):
|
||||
datetime_value = timezone.make_aware(datetime_value, tz)
|
||||
else:
|
||||
datetime_value = timezone.localtime(datetime_value, tz)
|
||||
return datetime_value, True
|
||||
|
||||
return None, False
|
||||
|
||||
|
||||
def _mission_queryset_for_employee(employee, *, include_details: bool = True):
|
||||
has_ending_reply_subquery = mission_models.MissionReply.objects.filter(
|
||||
mission_id=OuterRef("pk"),
|
||||
@@ -402,6 +434,7 @@ class MissionCategoryListCreateView(APIView):
|
||||
queryset = _mission_category_queryset_for_employee(employee)
|
||||
return Response(MissionCategorySerializer(queryset, many=True).data)
|
||||
|
||||
@extend_schema(request=MissionWriteSerializer, responses={201: MissionSerializer})
|
||||
def post(self, request):
|
||||
employee = _get_employee(request)
|
||||
serializer = MissionCategoryWriteSerializer(data=request.data, context={"employee": employee})
|
||||
@@ -466,6 +499,7 @@ class MissionCategoryDetailView(APIView):
|
||||
|
||||
class MissionListCreateView(APIView):
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
pagination_class = LimitedLimitOffsetPagination
|
||||
|
||||
def get(self, request):
|
||||
employee = _get_employee(request)
|
||||
@@ -482,7 +516,10 @@ class MissionListCreateView(APIView):
|
||||
if request.query_params.get("content_id"):
|
||||
queryset = queryset.filter(content_id=request.query_params["content_id"])
|
||||
|
||||
return Response(MissionSerializer(queryset, many=True).data)
|
||||
paginator = self.pagination_class()
|
||||
page = paginator.paginate_queryset(queryset, request, view=self)
|
||||
serializer = MissionSerializer(page, many=True)
|
||||
return paginator.get_paginated_response(serializer.data)
|
||||
|
||||
def post(self, request):
|
||||
employee = _get_employee(request)
|
||||
@@ -498,6 +535,7 @@ class MissionListCreateView(APIView):
|
||||
content_id=data.get("content_id"),
|
||||
extra=data.get("extra"),
|
||||
participant_ids=data.get("participant_ids"),
|
||||
employee_type_ids=data.get("employee_type_ids"),
|
||||
notify_if_unreplied=data.get("notify_if_unreplied", False),
|
||||
unreplied_notify_interval_minutes=data.get("unreplied_notify_interval_minutes"),
|
||||
unreplied_notify_max_count=data.get("unreplied_notify_max_count", 5),
|
||||
@@ -507,6 +545,65 @@ class MissionListCreateView(APIView):
|
||||
return Response(MissionSerializer(mission).data, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class MissionMyView(APIView):
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
pagination_class = LimitedLimitOffsetPagination
|
||||
|
||||
def get(self, request):
|
||||
employee = _get_employee(request)
|
||||
queryset = (
|
||||
_mission_queryset_for_employee(employee)
|
||||
.filter(Q(creator=employee) | Q(participants__employee=employee))
|
||||
.distinct()
|
||||
)
|
||||
|
||||
if _parse_bool_query_param(request, "created_by_me", default=False):
|
||||
queryset = queryset.filter(creator=employee)
|
||||
|
||||
for field in ["is_completed", "is_cancelled", "is_urgent"]:
|
||||
if request.query_params.get(field) is not None:
|
||||
queryset = queryset.filter(**{field: _parse_bool_query_param(request, field, default=False)})
|
||||
|
||||
created_at_from = request.query_params.get("created_at_from")
|
||||
if created_at_from is not None:
|
||||
dt, _has_time = _parse_date_or_datetime_query_param(created_at_from)
|
||||
if dt is None:
|
||||
raise serializers.ValidationError({"created_at_from": "必须是日期或日期时间"})
|
||||
queryset = queryset.filter(created_at__gte=dt)
|
||||
|
||||
created_at_to = request.query_params.get("created_at_to")
|
||||
if created_at_to is not None:
|
||||
dt, has_time = _parse_date_or_datetime_query_param(created_at_to)
|
||||
if dt is None:
|
||||
raise serializers.ValidationError({"created_at_to": "必须是日期或日期时间"})
|
||||
if has_time:
|
||||
queryset = queryset.filter(created_at__lte=dt)
|
||||
else:
|
||||
queryset = queryset.filter(created_at__lt=dt + timedelta(days=1))
|
||||
|
||||
paginator = self.pagination_class()
|
||||
page = paginator.paginate_queryset(queryset, request, view=self)
|
||||
serializer = MissionSerializer(page, many=True)
|
||||
return paginator.get_paginated_response(serializer.data)
|
||||
|
||||
|
||||
class MissionMyStatusCountsView(APIView):
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
def get(self, request):
|
||||
employee = _get_employee(request)
|
||||
queryset = mission_models.Mission.objects.filter(merchant=employee.merchant).filter(
|
||||
Q(creator=employee) | Q(participants__employee=employee)
|
||||
)
|
||||
counts = queryset.aggregate(
|
||||
total=Count("id", distinct=True),
|
||||
open=Count("id", filter=Q(is_completed=False, is_cancelled=False), distinct=True),
|
||||
completed=Count("id", filter=Q(is_completed=True, is_cancelled=False), distinct=True),
|
||||
cancelled=Count("id", filter=Q(is_cancelled=True), distinct=True),
|
||||
)
|
||||
return Response(counts)
|
||||
|
||||
|
||||
class MissionByPrintingOrderView(APIView):
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
@@ -568,6 +665,7 @@ class MissionDetailView(APIView):
|
||||
mission = self.get_object(request, mission_id)
|
||||
return Response(MissionSerializer(mission).data)
|
||||
|
||||
@extend_schema(request=MissionWriteSerializer, responses=MissionSerializer)
|
||||
def patch(self, request, mission_id):
|
||||
employee = _get_employee(request)
|
||||
mission = self.get_object(request, mission_id)
|
||||
@@ -589,6 +687,7 @@ class MissionDetailView(APIView):
|
||||
extra=(data["extra"] if "extra" in data else mission_services.UNSET),
|
||||
update_content_object=("content_type" in request.data or "content_id" in request.data),
|
||||
participant_ids=data.get("participant_ids"),
|
||||
employee_type_ids=data.get("employee_type_ids"),
|
||||
notify_if_unreplied=(
|
||||
data["notify_if_unreplied"]
|
||||
if "notify_if_unreplied" in data
|
||||
|
||||
Reference in New Issue
Block a user