diff --git a/apps/api/plane/api/serializers/project.py b/apps/api/plane/api/serializers/project.py index b22438ad51..c9a0a31c89 100644 --- a/apps/api/plane/api/serializers/project.py +++ b/apps/api/plane/api/serializers/project.py @@ -3,13 +3,7 @@ import random from rest_framework import serializers # Module imports -from plane.db.models import ( - Project, - ProjectIdentifier, - WorkspaceMember, - State, - Estimate, -) +from plane.db.models import Project, ProjectIdentifier, WorkspaceMember, State, Estimate from plane.utils.content_validator import ( validate_html_content, @@ -123,6 +117,7 @@ class ProjectCreateSerializer(BaseSerializer): def create(self, validated_data): identifier = validated_data.get("identifier", "").strip().upper() + if identifier == "": raise serializers.ValidationError(detail="Project Identifier is required") diff --git a/apps/api/plane/api/views/project.py b/apps/api/plane/api/views/project.py index fa735f557d..fbf6790516 100644 --- a/apps/api/plane/api/views/project.py +++ b/apps/api/plane/api/views/project.py @@ -210,7 +210,9 @@ class ProjectListCreateAPIEndpoint(BaseAPIView): """ try: workspace = Workspace.objects.get(slug=slug) + serializer = ProjectCreateSerializer(data={**request.data}, context={"workspace_id": workspace.id}) + if serializer.is_valid(): serializer.save() diff --git a/apps/api/plane/app/serializers/project.py b/apps/api/plane/app/serializers/project.py index d7c458d40d..b8a4136c96 100644 --- a/apps/api/plane/app/serializers/project.py +++ b/apps/api/plane/app/serializers/project.py @@ -13,7 +13,7 @@ from plane.db.models import ( ProjectIdentifier, DeployBoard, ProjectPublicMember, - IssueSequence + IssueSequence, ) from plane.utils.content_validator import ( validate_html_content, diff --git a/apps/api/plane/db/models/project.py b/apps/api/plane/db/models/project.py index 8495ac9df4..173ed43854 100644 --- a/apps/api/plane/db/models/project.py +++ b/apps/api/plane/db/models/project.py @@ -116,6 +116,11 @@ class Project(BaseModel): external_source = models.CharField(max_length=255, null=True, blank=True) external_id = models.CharField(max_length=255, blank=True, null=True) + def __init__(self, *args, **kwargs): + # Track if timezone is provided, if so, don't override it with the workspace timezone when saving + self.is_timezone_provided = kwargs.get("timezone") is not None + super().__init__(*args, **kwargs) + @property def cover_image_url(self): # Return cover image url @@ -155,7 +160,15 @@ class Project(BaseModel): ordering = ("-created_at",) def save(self, *args, **kwargs): + from plane.db.models import Workspace + self.identifier = self.identifier.strip().upper() + is_creating = self._state.adding + + if is_creating and not self.is_timezone_provided: + workspace = Workspace.objects.get(id=self.workspace_id) + self.timezone = workspace.timezone + return super().save(*args, **kwargs)