Remove second script, modify first

This commit is contained in:
zandercymatics 2025-01-07 08:42:56 -07:00
parent ca9a40caaf
commit 2c5c9de6dc
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
4 changed files with 24 additions and 188 deletions

View file

@ -919,36 +919,3 @@ Example (only requests): `./manage.py create_federal_portfolio --branch "executi
- Parameters #2-#3, you cannot use `--both` while using these. You must specify either `--parse_requests` or `--parse_domains` seperately. While all of these parameters are optional in that you do not need to specify all of them, - Parameters #2-#3, you cannot use `--both` while using these. You must specify either `--parse_requests` or `--parse_domains` seperately. While all of these parameters are optional in that you do not need to specify all of them,
you must specify at least one to run this script. you must specify at least one to run this script.
## Populate requested suborg
This script populates the "requested suborganization" fields on DomainRequest.
These fields are: requested_suborganization, suborganization_city, suborganization_state_territory.
This is done by pulling from organization_name, city, and state_territory.
The script will only parse records with a portfolio but no suborganization attached to it.
Additionally, it will not parse records wherein the organization name matches the portfolio org name.
### Running on sandboxes
#### Step 1: Login to CloudFoundry
```cf login -a api.fr.cloud.gov --sso```
#### Step 2: SSH into your environment
```cf ssh getgov-{space}```
Example: `cf ssh getgov-za`
#### Step 3: Create a shell instance
```/tmp/lifecycle/shell```
#### Step 4: Upload your csv to the desired sandbox
[Follow these steps](#use-scp-to-transfer-data-to-sandboxes) to upload the federal_cio csv to a sandbox of your choice.
#### Step 5: Running the script
To create a specific portfolio:
```./manage.py populate_requested_suborg```
### Running locally
#### Step 1: Running the script
```docker-compose exec app ./manage.py populate_requested_suborg```

View file

@ -1,52 +0,0 @@
import logging
from django.core.management import BaseCommand
from registrar.management.commands.utility.terminal_helper import PopulateScriptTemplate, TerminalColors, TerminalHelper
from registrar.models import DomainRequest
from registrar.models.utility.generic_helper import normalize_string
logger = logging.getLogger(__name__)
class Command(BaseCommand, PopulateScriptTemplate):
help = "Loops through each domain request object and populates requested suborg info"
def handle(self, **kwargs):
"""Loops through each DomainRequest object and populates
its last_status_update and first_submitted_date values"""
filter_conditions = {
"portfolio__isnull": False,
"organization_name__isnull": False,
"sub_organization__isnull": True,
"portfolio__organization_name__isnull": False,
}
fields_to_update = ["requested_suborganization", "suborganization_city", "suborganization_state_territory"]
self.mass_update_records(DomainRequest, filter_conditions, fields_to_update)
def update_record(self, record: DomainRequest):
"""Adds data to requested_suborganization, suborganization_city, and suborganization_state_territory."""
record.requested_suborganization = record.organization_name
record.suborganization_city = record.city
record.suborganization_state_territory = record.state_territory
message = (
f"Updating {record} => requested_suborg: {record.organization_name}, "
f"sub_city: {record.city}, suborg_state_territory: {record.state_territory}."
)
TerminalHelper.colorful_logger(logger.info, TerminalColors.OKBLUE, message)
def should_skip_record(self, record) -> bool:
"""Skips updating the record if the portfolio name is the same as the org name,
or if we are trying to update a record in an invalid status."""
invalid_statuses = [
DomainRequest.DomainRequestStatus.REJECTED,
DomainRequest.DomainRequestStatus.INELIGIBLE,
DomainRequest.DomainRequestStatus.STARTED,
]
if record.status in invalid_statuses:
return True
portfolio_normalized = normalize_string(record.portfolio.organization_name)
org_normalized = normalize_string(record.organization_name)
if portfolio_normalized == org_normalized:
return True
return False

View file

@ -343,9 +343,3 @@ def value_of_attribute(obj, attribute_name: str):
if callable(value): if callable(value):
value = value() value = value()
return value return value
def normalize_string(string_to_normalize: str) -> str:
"""Normalizes a given string. Returns a string without extra spaces, in all lowercase."""
new_string = " ".join(string_to_normalize.split())
return new_string.lower()

View file

@ -1588,6 +1588,30 @@ class TestCreateFederalPortfolio(TestCase):
self.assertTrue(all([creator == User.get_default_user() for creator in creators])) self.assertTrue(all([creator == User.get_default_user() for creator in creators]))
self.assertTrue(all([note == "Auto-generated record" for note in notes])) self.assertTrue(all([note == "Auto-generated record" for note in notes]))
def test_script_adds_requested_suborganization_information(self):
"""Tests that the script adds the requested suborg fields for domain requests"""
custom_suborg_request = completed_domain_request(
name="custom_org.gov",
status=DomainRequest.DomainRequestStatus.IN_REVIEW,
generic_org_type=DomainRequest.OrganizationChoices.FEDERAL,
federal_agency=self.executive_agency_2,
user=self.user,
organization_name="requested org name",
city="Austin",
state_territory=DomainRequest.StateTerritoryChoices.TEXAS
)
self.assertIsNone(custom_suborg_request.requested_suborganization)
self.assertIsNone(custom_suborg_request.suborganization_city)
self.assertIsNone(custom_suborg_request.suborganization_state_territory)
# Run the script and test it
self.run_create_federal_portfolio(branch="executive", parse_requests=True)
self.assertEqual(custom_suborg_request.requested_suborganization, "requested org name")
self.assertEqual(custom_suborg_request.suborganization_city, "Austin")
self.assertEqual(custom_suborg_request.suborganization_state_territory, DomainRequest.StateTerritoryChoices.TEXAS)
def test_create_multiple_portfolios_for_branch_executive(self): def test_create_multiple_portfolios_for_branch_executive(self):
"""Tests creating all portfolios under a given branch""" """Tests creating all portfolios under a given branch"""
federal_choice = DomainRequest.OrganizationChoices.FEDERAL federal_choice = DomainRequest.OrganizationChoices.FEDERAL
@ -1732,100 +1756,3 @@ class TestCreateFederalPortfolio(TestCase):
self.assertEqual(existing_portfolio.notes, "Old notes") self.assertEqual(existing_portfolio.notes, "Old notes")
self.assertEqual(existing_portfolio.creator, self.user) self.assertEqual(existing_portfolio.creator, self.user)
class TestPopulateRequestedSuborg(MockEppLib):
"""Tests for the populate_requested_suborg script"""
@less_console_noise_decorator
def setUp(self):
super().setUp()
self.user = create_user()
# Create a portfolio
self.portfolio = Portfolio.objects.create(organization_name="Test Portfolio", creator=self.user)
# Create a domain request with all required fields
self.complete_request = completed_domain_request(
name="complete.gov",
organization_name="Complete Org",
city="Washington",
state_territory="DC",
portfolio=self.portfolio,
status=DomainRequest.DomainRequestStatus.IN_REVIEW,
)
# Create a request that already has a suborganization
self.suborg = Suborganization.objects.create(name="Existing Suborg", portfolio=self.portfolio)
self.existing_suborg_request = completed_domain_request(
name="existing.gov",
organization_name="Existing Org",
city="New York",
state_territory="NY",
portfolio=self.portfolio,
sub_organization=self.suborg,
status=DomainRequest.DomainRequestStatus.IN_REVIEW,
)
# Create a request where org name matches portfolio name
self.matching_name_request = completed_domain_request(
name="matching.gov",
organization_name="Test Portfolio",
city="Boston",
state_territory="MA",
portfolio=self.portfolio,
user=self.user,
status=DomainRequest.DomainRequestStatus.IN_REVIEW,
)
def tearDown(self):
super().tearDown()
DomainRequest.objects.all().delete()
Suborganization.objects.all().delete()
Portfolio.objects.all().delete()
User.objects.all().delete()
@less_console_noise_decorator
def run_populate_requested_suborg(self):
"""Executes the populate_requested_suborg command"""
with patch(
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit",
return_value=True,
):
call_command("populate_requested_suborg")
@less_console_noise_decorator
def test_populate_requested_suborg_complete_request(self):
"""Tests that complete requests are updated correctly"""
self.run_populate_requested_suborg()
self.complete_request.refresh_from_db()
# Verify fields were populated correctly
self.assertEqual(self.complete_request.requested_suborganization, "Complete Org")
self.assertEqual(self.complete_request.suborganization_city, "Washington")
self.assertEqual(self.complete_request.suborganization_state_territory, "DC")
@less_console_noise_decorator
def test_populate_requested_suborg_existing_suborg(self):
"""Tests that requests with existing suborgs are skipped"""
self.run_populate_requested_suborg()
self.existing_suborg_request.refresh_from_db()
# Verify the request wasn't modified
self.assertEqual(self.existing_suborg_request.sub_organization, self.suborg)
self.assertIsNone(self.existing_suborg_request.requested_suborganization)
self.assertIsNone(self.existing_suborg_request.suborganization_city)
self.assertIsNone(self.existing_suborg_request.suborganization_state_territory)
@less_console_noise_decorator
def test_populate_requested_suborg_matching_name(self):
"""Tests that requests with matching org/portfolio names are skipped"""
self.run_populate_requested_suborg()
self.matching_name_request.refresh_from_db()
# Verify the request wasn't modified since org name matches portfolio name
self.assertIsNone(self.matching_name_request.requested_suborganization)
self.assertIsNone(self.matching_name_request.suborganization_city)
self.assertIsNone(self.matching_name_request.suborganization_state_territory)