Removal logic

This commit is contained in:
zandercymatics 2024-12-17 08:34:58 -07:00
parent 79077cce31
commit 4572b52aad
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
4 changed files with 50 additions and 33 deletions

View file

@ -17,6 +17,7 @@ from registrar.models import Contact, DomainRequest, DraftDomain, Domain, Federa
from registrar.templatetags.url_helpers import public_site_url from registrar.templatetags.url_helpers import public_site_url
from registrar.utility.enums import ValidationReturnType from registrar.utility.enums import ValidationReturnType
from registrar.utility.constants import BranchChoices from registrar.utility.constants import BranchChoices
from django.core.exceptions import ValidationError
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -78,6 +79,20 @@ class RequestingEntityForm(RegistrarForm):
# Otherwise just return the suborg as normal # Otherwise just return the suborg as normal
return self.cleaned_data.get("sub_organization") return self.cleaned_data.get("sub_organization")
def clean_requested_suborganization(self):
name = self.cleaned_data.get('requested_suborganization')
if name and Suborganization.objects.filter(
name__iexact=name,
portfolio=self.domain_request.portfolio,
name__isnull=False,
portfolio__isnull=False
).exists():
raise ValidationError(
"This suborganization already exists. "
"Choose a new name, or select it directly if you would like to use it."
)
return name
def full_clean(self): def full_clean(self):
"""Validation logic to remove the custom suborganization value before clean is triggered. """Validation logic to remove the custom suborganization value before clean is triggered.
Without this override, the form will throw an 'invalid option' error.""" Without this override, the form will throw an 'invalid option' error."""
@ -114,7 +129,7 @@ class RequestingEntityForm(RegistrarForm):
if requesting_entity_is_suborganization == "True": if requesting_entity_is_suborganization == "True":
if is_requesting_new_suborganization: if is_requesting_new_suborganization:
# Validate custom suborganization fields # Validate custom suborganization fields
if not cleaned_data.get("requested_suborganization"): if not cleaned_data.get("requested_suborganization") and "requested_suborganization" not in self.errors:
self.add_error("requested_suborganization", "Enter the name of your suborganization.") self.add_error("requested_suborganization", "Enter the name of your suborganization.")
if not cleaned_data.get("suborganization_city"): if not cleaned_data.get("suborganization_city"):
self.add_error("suborganization_city", "Enter the city where your suborganization is located.") self.add_error("suborganization_city", "Enter the city where your suborganization is located.")

View file

@ -1,17 +0,0 @@
# Generated by Django 4.2.10 on 2024-12-16 17:02
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("registrar", "0139_alter_domainrequest_action_needed_reason"),
]
operations = [
migrations.AlterUniqueTogether(
name="suborganization",
unique_together={("name", "portfolio")},
),
]

View file

@ -12,6 +12,7 @@ from registrar.models.utility.generic_helper import CreateOrUpdateOrganizationTy
from registrar.utility.errors import FSMDomainRequestError, FSMErrorCodes from registrar.utility.errors import FSMDomainRequestError, FSMErrorCodes
from registrar.utility.constants import BranchChoices from registrar.utility.constants import BranchChoices
from auditlog.models import LogEntry from auditlog.models import LogEntry
from django.core.exceptions import ValidationError
from registrar.utility.waffle import flag_is_active_for_user from registrar.utility.waffle import flag_is_active_for_user
@ -796,6 +797,7 @@ class DomainRequest(TimeStampedModel):
return True return True
def delete_and_clean_up_domain(self, called_from): def delete_and_clean_up_domain(self, called_from):
# Delete the approved domain
try: try:
# Clean up the approved domain # Clean up the approved domain
domain_state = self.approved_domain.state domain_state = self.approved_domain.state
@ -809,18 +811,38 @@ class DomainRequest(TimeStampedModel):
logger.error(err) logger.error(err)
logger.error(f"Can't query an approved domain while attempting {called_from}") logger.error(f"Can't query an approved domain while attempting {called_from}")
# Clean up any created suborgs, assuming its for this record only # Delete the suborg as long as this is the only place it is used
if self.sub_organization is not None: self._cleanup_dangling_suborg()
request_suborg_count = self.request_sub_organization.count()
domain_suborgs = self.DomainRequest_info.filter( def _cleanup_dangling_suborg(self):
sub_organization=self.sub_organization """Deletes the existing suborg if its only being used by the deleted record"""
).count() # Nothing to delete, so we just smile and walk away
if request_suborg_count == 1 and domain_suborgs.count() <= 1: if self.sub_organization is None:
# if domain_suborgs.count() == 1: return
# domain_info = domain_suborgs.first()
# domain_info.sub_organization = None Suborganization = apps.get_model("registrar.Suborganization")
# domain_info.save()
self.sub_organization.delete() # Stored as so because we need to set the reference to none first,
# so we can't just use the self.sub_organization property
suborg = Suborganization.objects.get(id=self.sub_organization.id)
requests = suborg.request_sub_organization
domain_infos = suborg.information_sub_organization
# Check if this is the only reference to the suborganization
if requests.count() != 1 or domain_infos.count() > 1:
return
# Remove the suborganization reference from request.
self.sub_organization = None
self.save()
# Remove the suborganization reference from domain if it exists.
if domain_infos.count() == 1:
domain_infos.update(sub_organization=None)
# Delete the now-orphaned suborganization
logger.info(f"_cleanup_dangling_suborg() -> Deleting orphan suborganization: {suborg}")
suborg.delete()
def _send_status_update_email( def _send_status_update_email(
self, self,

View file

@ -9,9 +9,6 @@ class Suborganization(TimeStampedModel):
Suborganization under an organization (portfolio) Suborganization under an organization (portfolio)
""" """
class Meta:
unique_together = ["name", "portfolio"]
name = models.CharField( name = models.CharField(
unique=True, unique=True,
max_length=1000, max_length=1000,