Skip to content

Commit

Permalink
Merge pull request #5771 from uktrade/TET-851-company-activity-great-…
Browse files Browse the repository at this point in the history
…data

Add great export enquiries to company activity
  • Loading branch information
bau123 authored Nov 8, 2024
2 parents 3d87c69 + 7b85f9a commit 3f7b38e
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 6 deletions.
7 changes: 7 additions & 0 deletions datahub/cleanup/test/commands/test_delete_old_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
SubsidiaryFactory,
)
from datahub.company_activity.tests.factories import (
CompanyActivityGreatExportEnquiryFactory,
CompanyActivityInteractionFactory,
CompanyActivityInvestmentProjectFactory,
CompanyActivityOmisOrderFactory,
Expand Down Expand Up @@ -222,6 +223,12 @@
'expired_objects_kwargs': [],
'unexpired_objects_kwargs': [],
},
{
'factory': CompanyActivityGreatExportEnquiryFactory,
'field': 'company',
'expired_objects_kwargs': [],
'unexpired_objects_kwargs': [],
},
{
'factory': EYBLeadFactory,
'field': 'company',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
COMPANY_ACTIVITY_CREATED_BY_MODELS = [
CompanyReferralFactory,
CompanyInteractionFactory,
GreatExportEnquiryFactory,
InvestmentProjectFactory,
OrderFactory,
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 4.2.16 on 2024-11-04 16:59

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('company_activity', '0011_revert_onetoone_to_foreignkey'),
]

operations = [
migrations.AddField(
model_name='companyactivity',
name='great',
field=models.ForeignKey(blank=True, help_text='If related to an great export enquiry, must not have relations to any other activity (referral, event etc)', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='activity', to='company_activity.greatexportenquiry', unique=True),
),
migrations.AlterField(
model_name='companyactivity',
name='activity_source',
field=models.CharField(choices=[('interaction', 'interaction'), ('referral', 'referral'), ('event', 'event'), ('investment', 'investment'), ('order', 'order'), ('great', 'great')], help_text='The type of company activity, such as an interaction, event, referral etc.', max_length=255),
),
]
14 changes: 14 additions & 0 deletions datahub/company_activity/models/company_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ActivitySource(models.TextChoices):
event = ('event', 'event')
investment = ('investment', 'investment')
order = ('order', 'order')
great = ('great', 'great')

id = models.UUIDField(primary_key=True, default=uuid.uuid4)
company = models.ForeignKey(
Expand Down Expand Up @@ -100,6 +101,19 @@ class ActivitySource(models.TextChoices):
),
)

great = models.ForeignKey(
'company_activity.GreatExportEnquiry',
unique=True,
null=True,
blank=True,
related_name='activity',
on_delete=models.CASCADE,
help_text=(
'If related to an great export enquiry, must not have relations to any other activity '
'(referral, event etc)'
),
)

def __str__(self):
"""Readable name for CompanyActivity"""
return f'Activity from "{self.activity_source}" for company: {self.company.name}'
18 changes: 17 additions & 1 deletion datahub/company_activity/models/great.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import uuid

from django.conf import settings
from django.db import models
from django.db import models, transaction


from datahub.company.models.company import Company
from datahub.company.models.contact import Contact
from datahub.company_activity.models import CompanyActivity
from datahub.core import reversion
from datahub.metadata import models as metadata_models

Expand Down Expand Up @@ -112,3 +114,17 @@ class GreatExportEnquiry(models.Model):
submission_type = models.CharField(max_length=MAX_LENGTH)
submission_action = models.CharField(max_length=MAX_LENGTH)
created_on = models.DateTimeField(auto_now_add=True)

def save(self, *args, **kwargs):
with transaction.atomic():
super().save(*args, **kwargs)
if not self.company_id:
return
CompanyActivity.objects.update_or_create(
great_id=self.id,
activity_source=CompanyActivity.ActivitySource.great,
defaults={
'date': self.created_on,
'company_id': self.company_id,
},
)
32 changes: 31 additions & 1 deletion datahub/company_activity/tasks/sync.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging

from datahub.company_activity.models import CompanyActivity
from datahub.company_activity.models import CompanyActivity, GreatExportEnquiry
from datahub.company_referral.models import CompanyReferral
from datahub.core.queues.constants import HALF_DAY_IN_SECONDS
from datahub.core.queues.job_scheduler import job_scheduler
Expand Down Expand Up @@ -134,6 +134,36 @@ def relate_company_activity_to_orders(batch_size=500):
bulk_create_activity(objs, batch_size)


def relate_company_activity_to_great(batch_size=500):
"""
Grabs all great export enquiry so they can be related to in the
`CompanyActivity` model with a bulk_create. Excludes any
great export enquiry already associated in the CompanyActivity model.
"""
activity = set(
CompanyActivity.objects.filter(
great_id__isnull=False,
).values_list('great_id', flat=True),
)

great_export_enquiries = GreatExportEnquiry.objects.filter(
company_id__isnull=False,
).values('id', 'created_on', 'company_id')

objs = [
CompanyActivity(
great_id=great_export_enquiry['id'],
date=great_export_enquiry['created_on'],
company_id=great_export_enquiry['company_id'],
activity_source=CompanyActivity.ActivitySource.great,
)
for great_export_enquiry in great_export_enquiries
if great_export_enquiry['id'] not in activity
]

bulk_create_activity(objs, batch_size)


def schedule_sync_data_to_company_activity(relate_function):
"""
Schedules a task for the given function.
Expand Down
31 changes: 27 additions & 4 deletions datahub/company_activity/tests/factories.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import factory.fuzzy
from django.utils.timezone import now

from datahub.company.test.factories import CompanyFactory
from datahub.company.test.factories import CompanyFactory, ContactFactory
from datahub.company_activity.models import CompanyActivity
from datahub.company_referral.test.factories import CompanyReferralFactory
from datahub.interaction.test.factories import CompanyInteractionFactory
Expand All @@ -27,9 +27,9 @@ class Meta:

class CompanyActivityInteractionFactory(CompanyActivityBaseFactory):
"""
CompanyActivity factory with an interaction.
Be careful for tests as creating an Interaction already creates a CompanyActivity
for the interaction, so calling this creates two CompanyActivities.
Overwrite the _create to prevent the CompanyActivity from saving to the database.
This is due to the Interaction already creating the CompanyActivity inside its
model save.
"""

activity_source = CompanyActivity.ActivitySource.interaction
Expand Down Expand Up @@ -190,10 +190,33 @@ class GreatExportEnquiryFactory(factory.django.DjangoModelFactory):
actor_dit_is_blacklisted = False
actor_dit_is_whitelisted = False
actor_dit_blacklisted_reason = None
contact = factory.SubFactory(ContactFactory)

@factory.post_generation
def set_markets(self, create, extracted, **kwargs):
self.data_markets.set([CountryFactory()])

class Meta:
model = 'company_activity.GreatExportEnquiry'


class CompanyActivityGreatExportEnquiryFactory(CompanyActivityBaseFactory):
"""
CompanyActivity factory with an great export enquiry.
"""

activity_source = CompanyActivity.ActivitySource.great
great = factory.SubFactory(GreatExportEnquiryFactory)

class Meta:
model = 'company_activity.CompanyActivity'

@classmethod
def _create(cls, model_class, *args, **kwargs):
"""
Overwrite the _create to prevent the CompanyActivity from saving to the database.
This is due to the great export enquiry already creating the CompanyActivity inside its
model save.
"""
obj = model_class(*args, **kwargs)
return CompanyActivity.objects.get(great_id=obj.great_id)
48 changes: 48 additions & 0 deletions datahub/company_activity/tests/models/test_great_export_enquiry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import pytest

from datahub.company.test.factories import CompanyFactory
from datahub.company_activity.models import CompanyActivity
from datahub.company_activity.tests.factories import GreatExportEnquiryFactory


@pytest.mark.django_db
class TestGreatExportEnquiry:
"""Tests for the Great Export Enquiry model."""

def test_save(self):
"""
Test save also saves to the `CompanyActivity` model and does not save to the
`CompanyActivity` model if it already exists.
"""
assert not CompanyActivity.objects.all().exists()
great = GreatExportEnquiryFactory()
assert CompanyActivity.objects.all().count() == 1

company_activity = CompanyActivity.objects.get(great_id=great.id)
assert company_activity.company_id == great.company_id
assert company_activity.date == great.created_on
assert company_activity.activity_source == CompanyActivity.ActivitySource.great

# Update and save the great export enquiry and ensure if doesn't create another
# `CompanyActivity` and only updates it
new_company = CompanyFactory()
great.company_id = new_company.id
great.save()

assert CompanyActivity.objects.all().count() == 1
company_activity.refresh_from_db()
assert company_activity.company_id == new_company.id

great.delete()
assert not CompanyActivity.objects.all().exists()

def test_save_with_no_company(self):
"""
Test save does not save to the `CompanyActivity` model
"""
assert not CompanyActivity.objects.all().exists()

# Try to save the great export enquiry with no company id which will not work
GreatExportEnquiryFactory(company_id=None)

assert not CompanyActivity.objects.all().exists()
17 changes: 17 additions & 0 deletions datahub/company_activity/tests/test_tasks/test_factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pytest

from datahub.company_activity.models import CompanyActivity
from datahub.company_activity.tests.factories import CompanyActivityGreatExportEnquiryFactory


@pytest.mark.django_db
class TestCompanyActivityGreatExportEnquiryFactory:

def test_factory_does_not_create_duplicates(self):
"""
As the GreatExportEnquiry models save method is overwritten to create a company
activity. The _create method on the factory returns the created activity from the save
rather than creating a new one causing duplicates.
"""
CompanyActivityGreatExportEnquiryFactory()
assert CompanyActivity.objects.count() == 1
77 changes: 77 additions & 0 deletions datahub/company_activity/tests/test_tasks/test_great_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from unittest import mock

import pytest

from datahub.company_activity.models import CompanyActivity
from datahub.company_activity.tasks.sync import (
relate_company_activity_to_great,
schedule_sync_data_to_company_activity,
)
from datahub.company_activity.tests.factories import GreatExportEnquiryFactory


@pytest.mark.django_db
class TestCompanyActivityGreatTasks:
"""
Tests for the schedule_sync_data_to_company_activity task for great export enquiry.
"""

def test_great_export_enquiry_are_copied_to_company_activity(self):
"""
Test that great export enquiry are added to the CompanyActivity model.
"""
great = GreatExportEnquiryFactory()
GreatExportEnquiryFactory.create_batch(3)

# Remove the created CompanyActivities added by the Great model `save` method
# to mimic already existing data in staging and prod database.
CompanyActivity.objects.all().delete()
assert CompanyActivity.objects.count() == 0

# Check the "existing" great are added to the company activity model
schedule_sync_data_to_company_activity(relate_company_activity_to_great)
assert CompanyActivity.objects.count() == 4

company_activity = CompanyActivity.objects.get(great_id=great.id)
assert company_activity.date == great.created_on
assert company_activity.activity_source == CompanyActivity.ActivitySource.great
assert company_activity.company_id == great.company.id

@mock.patch('datahub.company_activity.models.CompanyActivity.objects.bulk_create')
def test_great_export_enquiry_are_bulk_created_in_batches(self, mocked_bulk_create, caplog):
"""
Test that great export enquiries are bulk created in batches.
"""
caplog.set_level('INFO')
batch_size = 5

GreatExportEnquiryFactory.create_batch(10)

# Delete any activity created through the great export enquiry save method.
CompanyActivity.objects.all().delete()
assert CompanyActivity.objects.count() == 0

# Ensure great export enquiry are bulk_created
relate_company_activity_to_great(batch_size)
assert mocked_bulk_create.call_count == 2

assert (
f'Creating in batches of: {batch_size} CompanyActivities. 10 remaining.' in caplog.text
)
assert (
f'Creating in batches of: {batch_size} CompanyActivities. 5 remaining.' in caplog.text
)
assert 'Finished bulk creating CompanyActivities.' in caplog.text

def test_great_export_enquiry_with_a_company_activity_are_not_added_again(self):
"""
Test that great export enquiries which are already part of the `CompanyActivity` model
are not added again.
"""
GreatExportEnquiryFactory.create_batch(4)

assert CompanyActivity.objects.count() == 4

# Check count remains unchanged.
schedule_sync_data_to_company_activity(relate_company_activity_to_great)
assert CompanyActivity.objects.count() == 4

0 comments on commit 3f7b38e

Please sign in to comment.