| 55 | |
| 56 | |
| 57 | class ChangeRequest( # type: ignore[django-manager-missing] |
| 58 | LifecycleModelMixin, # type: ignore[misc] |
| 59 | SoftDeleteExportableModel, |
| 60 | abstract_base_auditable_model_factory(["uuid"]), # type: ignore[misc] |
| 61 | ): |
| 62 | related_object_type = RelatedObjectType.CHANGE_REQUEST |
| 63 | history_record_class_path = "features.workflows.core.models.HistoricalChangeRequest" |
| 64 | |
| 65 | created_at = models.DateTimeField(auto_now_add=True) |
| 66 | updated_at = models.DateTimeField(auto_now=True) |
| 67 | |
| 68 | title = models.CharField(max_length=500) |
| 69 | description = models.TextField(blank=True, null=True) |
| 70 | |
| 71 | # We allow null here so that deleting users does not cascade to deleting change |
| 72 | # requests which can be used for historical purposes. |
| 73 | user = models.ForeignKey( |
| 74 | settings.AUTH_USER_MODEL, |
| 75 | on_delete=models.SET_NULL, |
| 76 | related_name="change_requests", |
| 77 | null=True, |
| 78 | ) |
| 79 | |
| 80 | project = models.ForeignKey( |
| 81 | "projects.Project", |
| 82 | on_delete=models.CASCADE, |
| 83 | related_name="change_requests", |
| 84 | null=False, |
| 85 | ) |
| 86 | |
| 87 | environment = models.ForeignKey( |
| 88 | "environments.Environment", |
| 89 | on_delete=models.CASCADE, |
| 90 | related_name="change_requests", |
| 91 | null=True, |
| 92 | ) |
| 93 | |
| 94 | committed_at = models.DateTimeField(null=True) |
| 95 | committed_by = models.ForeignKey( |
| 96 | settings.AUTH_USER_MODEL, |
| 97 | on_delete=models.SET_NULL, |
| 98 | related_name="committed_change_requests", |
| 99 | null=True, |
| 100 | ) |
| 101 | |
| 102 | ignore_conflicts = models.BooleanField(default=False) |
| 103 | |
| 104 | class Meta: |
| 105 | # Explicit ordering to prevent pagination warnings. |
| 106 | ordering = ("id",) |
| 107 | |
| 108 | def approve(self, user: "FFAdminUser"): # type: ignore[no-untyped-def] |
| 109 | if user.id == self.user_id: |
| 110 | raise CannotApproveOwnChangeRequest( |
| 111 | "User cannot approve their own Change Request." |
| 112 | ) |
| 113 | |
| 114 | ChangeRequestApproval.objects.update_or_create( |
nothing calls this directly
no test coverage detected
searching dependent graphs…