Skip to content

Commit

Permalink
Add one-off command to modify referred projects (#5807)
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverjwroberts authored Nov 20, 2024
1 parent c5bcc2a commit 12ff05e
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
1 change: 1 addition & 0 deletions datahub/investment/project/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class SpecificProgramme(Enum):
'Advanced Engineering Supply Chain',
'6513f918-4263-4516-8abb-8e4a6a4de857',
)
referred_to_eyb = Constant('Referred to EYB', '3902b516-e553-4f54-b389-0a5db87ea507')


class InvestorType(Enum):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import logging

from django.core.management.base import BaseCommand

from datahub.investment.project.constants import SpecificProgramme as SpecificProgrammeConstants
from datahub.investment.project.models import (
InvestmentProject,
SpecificProgramme,
)


REFERRED_TO_EYB_PROGRAMME_ID = SpecificProgrammeConstants.referred_to_eyb.value.id
REFERRED_STATUS_VALUE = InvestmentProject.Status.REFERRED.value
ONGOING_STATUS_VALUE = InvestmentProject.Status.ONGOING.value


logger = logging.getLogger(__name__)


# TODO: Remove command once it has been run as one-off data modification


class Command(BaseCommand):
"""Command to do a one-off modification of referred investment projects."""

help = 'Modifies referred investment projects according to business rules.'

def handle(self, *args, **options):
"""Method to iterate over `referred` projects and modify them.
Modifications include:
- Add the new `Referred to EYB` specific programme to their list of specific programmes
- Set their status as `Ongoing`
"""
try:
referred_projects = InvestmentProject.objects.filter(
status=REFERRED_STATUS_VALUE,
)
referred_to_eyb_programme = SpecificProgramme.objects.get(
pk=REFERRED_TO_EYB_PROGRAMME_ID,
)
if referred_projects.exists():
logger.info(f'Found {referred_projects.count()} referred projects. Modifying...')
# many-to-many field needs to be updated individually
for project in referred_projects:
project.specific_programmes.add(referred_to_eyb_programme)
# bulk update status field
referred_projects.update(status=ONGOING_STATUS_VALUE)
logger.info('Finished modifying referred projects.')
else:
logger.warning('No referred projects found. Exiting...')
except Exception as e:
logger.error(f'An error occurred trying to modify referred projects: {str(e)}')
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import logging

import pytest

from django.core.management import call_command

from datahub.investment.project.constants import SpecificProgramme as SpecificProgrammeConstants
from datahub.investment.project.models import (
InvestmentProject,
SpecificProgramme,
)
from datahub.investment.project.test.factories import InvestmentProjectFactory


REFERRED_TO_EYB_PROGRAMME_ID = SpecificProgrammeConstants.referred_to_eyb.value.id
REFERRED_STATUS_VALUE = InvestmentProject.Status.REFERRED.value
ONGOING_STATUS_VALUE = InvestmentProject.Status.ONGOING.value
DELAYED_STATUS_VALUE = InvestmentProject.Status.DELAYED.value


pytestmark = pytest.mark.django_db


# TODO: Remove file once command has been run as one-off data modification


def test_modify_referred_projects(caplog):
referred_to_eyb_programme = SpecificProgramme.objects.get(
pk=REFERRED_TO_EYB_PROGRAMME_ID,
)

# setup investment projects
referred_project = InvestmentProjectFactory(
status=REFERRED_STATUS_VALUE,
specific_programmes=[],
)
other_referred_project = InvestmentProjectFactory(
status=REFERRED_STATUS_VALUE,
specific_programmes=[referred_to_eyb_programme],
)
InvestmentProjectFactory(
status=ONGOING_STATUS_VALUE,
specific_programmes=[],
)
InvestmentProjectFactory(
status=DELAYED_STATUS_VALUE,
specific_programmes=[],
)

# initial assertions
assert InvestmentProject.objects.count() == 4

assert referred_project.status == REFERRED_STATUS_VALUE
assert referred_project.specific_programmes.count() == 0

assert other_referred_project.status == REFERRED_STATUS_VALUE
assert other_referred_project.specific_programmes.count() == 1
assert referred_to_eyb_programme in other_referred_project.specific_programmes.all()

# execute job
with caplog.at_level(logging.INFO):
call_command('modify_referred_projects')
assert 'Found 2 referred projects. Modifying...' in caplog.text
assert 'Finished modifying referred projects.' in caplog.text

# final assertions
referred_project.refresh_from_db()
assert referred_project.status == ONGOING_STATUS_VALUE
assert referred_project.specific_programmes.count() == 1
assert referred_to_eyb_programme in referred_project.specific_programmes.all()

other_referred_project.refresh_from_db()
assert other_referred_project.status == ONGOING_STATUS_VALUE
assert other_referred_project.specific_programmes.count() == 1

assert InvestmentProject.objects.count() == 4
assert InvestmentProject.objects.filter(status=ONGOING_STATUS_VALUE).count() == 3
assert InvestmentProject.objects.filter(
specific_programmes=REFERRED_TO_EYB_PROGRAMME_ID,
).count() == 2


def test_modify_referred_projects_when_theres_no_projects(caplog):
with caplog.at_level(logging.INFO):
call_command('modify_referred_projects')
assert 'No referred projects found. Exiting...' in caplog.text


def test_modify_referred_projects_handles_error(caplog):
# cause error by deleting the Referred to EYB specific programme
SpecificProgramme.objects.get(
pk=REFERRED_TO_EYB_PROGRAMME_ID,
).delete()
with caplog.at_level(logging.ERROR):
call_command('modify_referred_projects')
assert 'An error occurred trying to modify referred projects' in caplog.text

0 comments on commit 12ff05e

Please sign in to comment.