Skip to content

Commit 97b6d67

Browse files
committed
Remove contact field from interactions in main API
1 parent e6b13a7 commit 97b6d67

File tree

6 files changed

+6
-321
lines changed

6 files changed

+6
-321
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``GET,POST /v3/interaction``, ``GET,PATCH /v3/interaction/<id>``: The deprecated ``contact`` field was removed. Please use ``contacts`` instead.

datahub/interaction/serializers.py

+1-72
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from django.utils.translation import ugettext_lazy
44
from rest_framework import serializers
5-
from rest_framework.settings import api_settings
65

76
from datahub.company.models import Company, Contact
87
from datahub.company.serializers import NestedAdviserField
@@ -28,32 +27,6 @@
2827
from datahub.metadata.models import Service, Team
2928

3029

31-
class _ManyRelatedAsSingleItemField(NestedRelatedField):
32-
"""
33-
Serialiser field that makes a to-many field behave like a to-one field.
34-
35-
Use for temporary backwards compatibility when migrating a to-one field to be a to-many field
36-
(so that a to-one field can be emulated using a to-many field).
37-
38-
This isn't intended to be used in any other way as if the to-many field contains multiple
39-
items, only one of them will be returned, and all of them will overwritten on updates.
40-
41-
TODO Remove this once contact has been removed from interactions.
42-
"""
43-
44-
def run_validation(self, data=serializers.empty):
45-
"""Validate a user-provided value and return the internal value (converted to a list)."""
46-
validated_value = super().run_validation(data)
47-
return [validated_value] if validated_value else []
48-
49-
def to_representation(self, value):
50-
"""Converts a query set to a dict representation of the first item in the query set."""
51-
if not value.exists():
52-
return None
53-
54-
return super().to_representation(value.first())
55-
56-
5730
class InteractionSerializer(serializers.ModelSerializer):
5831
"""V3 interaction serialiser."""
5932

@@ -76,38 +49,22 @@ class InteractionSerializer(serializers.ModelSerializer):
7649
'invalid_when_no_policy_feedback': ugettext_lazy(
7750
'This field is only valid when policy feedback has been provided.',
7851
),
79-
'one_contact_field': ugettext_lazy(
80-
'Only one of contact and contacts should be provided.',
81-
),
8252
'too_many_contacts_for_event_service_delivery': ugettext_lazy(
8353
'Only one contact can be provided for event service deliveries.',
8454
),
8555
}
8656

8757
company = NestedRelatedField(Company)
88-
# TODO Remove contact following deprecation period
89-
contact = _ManyRelatedAsSingleItemField(
90-
Contact,
91-
extra_fields=(
92-
'name',
93-
'first_name',
94-
'last_name',
95-
'job_title',
96-
),
97-
source='contacts',
98-
required=False,
99-
)
100-
# TODO Make required once contact has been removed
10158
contacts = NestedRelatedField(
10259
Contact,
10360
many=True,
61+
allow_empty=False,
10462
extra_fields=(
10563
'name',
10664
'first_name',
10765
'last_name',
10866
'job_title',
10967
),
110-
required=False,
11168
)
11269
dit_adviser = NestedAdviserField()
11370
created_by = NestedAdviserField(read_only=True)
@@ -131,24 +88,6 @@ class InteractionSerializer(serializers.ModelSerializer):
13188
required=False,
13289
)
13390

134-
def to_internal_value(self, data):
135-
"""
136-
Checks that contact and contacts haven't both been provided.
137-
138-
Note: On serialisers, to_internal_value() is called before validate().
139-
140-
TODO Remove once contact removed from the API.
141-
"""
142-
if 'contact' in data and 'contacts' in data:
143-
error = {
144-
api_settings.NON_FIELD_ERRORS_KEY: [
145-
self.error_messages['one_contact_field'],
146-
],
147-
}
148-
raise serializers.ValidationError(error, code='one_contact_field')
149-
150-
return super().to_internal_value(data)
151-
15291
def validate(self, data):
15392
"""
15493
Removes the semi-virtual field is_event from the data.
@@ -182,8 +121,6 @@ class Meta:
182121
fields = (
183122
'id',
184123
'company',
185-
# TODO Remove contact following deprecation period
186-
'contact',
187124
'contacts',
188125
'created_on',
189126
'created_by',
@@ -216,14 +153,6 @@ class Meta:
216153
HasAssociatedInvestmentProjectValidator(),
217154
ContactsBelongToCompanyValidator(),
218155
RulesBasedValidator(
219-
# Because contacts could come from either contact or contacts, this has to be at
220-
# the object level
221-
# TODO Remove once contact has been removed and required=False removed from
222-
# contacts
223-
ValidationRule(
224-
'required',
225-
OperatorRule('contacts', bool),
226-
),
227156
ValidationRule(
228157
'required',
229158
OperatorRule('communication_channel', bool),

datahub/interaction/test/test_serializers.py

-49
This file was deleted.

datahub/interaction/test/views/test_common.py

+2-136
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ def test_invalid_kind_is_rejected(self, kind):
4646
'company': {
4747
'id': company.pk,
4848
},
49-
'contact': {
49+
'contacts': [{
5050
'id': contact.pk,
51-
},
51+
}],
5252
'date': '2017-04-18',
5353
'dit_adviser': {
5454
'id': adviser.pk,
@@ -70,48 +70,6 @@ def test_invalid_kind_is_rejected(self, kind):
7070
'kind': [f'"{kind}" is not a valid choice.'],
7171
}
7272

73-
def test_contact_copied_to_contacts(self):
74-
"""
75-
Test that the value provided in the contact field is copied to contacts when an
76-
interaction is created.
77-
78-
TODO: remove once the contacts field has fully replaced the contact field.
79-
"""
80-
company = CompanyFactory()
81-
contact = ContactFactory(company=company)
82-
communication_channel = random_obj_for_model(CommunicationChannel)
83-
84-
url = reverse('api-v3:interaction:collection')
85-
request_data = {
86-
'kind': Interaction.KINDS.interaction,
87-
'communication_channel': communication_channel.pk,
88-
'subject': 'whatever',
89-
'date': date.today().isoformat(),
90-
'dit_adviser': {
91-
'id': self.user.pk,
92-
},
93-
'company': {
94-
'id': company.pk,
95-
},
96-
'contact': {
97-
'id': contact.pk,
98-
},
99-
'service': {
100-
'id': random_obj_for_model(ServiceModel).pk,
101-
},
102-
'dit_team': {
103-
'id': self.user.dit_team.pk,
104-
},
105-
'was_policy_feedback_provided': False,
106-
}
107-
108-
api_client = self.create_api_client()
109-
response = api_client.post(url, request_data)
110-
assert response.status_code == status.HTTP_201_CREATED
111-
interaction = Interaction.objects.get(pk=response.json()['id'])
112-
assert interaction.contact == contact
113-
assert list(interaction.contacts.all()) == [contact]
114-
11573
def test_contacts_copied_to_contact(self):
11674
"""
11775
Test that the value provided in the contacts field is copied to contact when an
@@ -154,50 +112,6 @@ def test_contacts_copied_to_contact(self):
154112
assert interaction.contact == contacts[0]
155113
assert set(interaction.contacts.all()) == set(contacts)
156114

157-
def test_providing_contact_and_contacts_returns_an_error(self):
158-
"""
159-
Test that if both contact and contacts are provided, an error is returned.
160-
161-
TODO: remove once the contacts field has fully replaced the contact field.
162-
"""
163-
company = CompanyFactory()
164-
contact = ContactFactory()
165-
communication_channel = random_obj_for_model(CommunicationChannel)
166-
167-
url = reverse('api-v3:interaction:collection')
168-
request_data = {
169-
'kind': Interaction.KINDS.interaction,
170-
'communication_channel': communication_channel.pk,
171-
'subject': 'whatever',
172-
'date': date.today().isoformat(),
173-
'dit_adviser': {
174-
'id': self.user.pk,
175-
},
176-
'company': {
177-
'id': company.pk,
178-
},
179-
'contact': {
180-
'id': contact.pk,
181-
},
182-
'contacts': [{
183-
'id': contact.pk,
184-
}],
185-
'service': {
186-
'id': random_obj_for_model(ServiceModel).pk,
187-
},
188-
'dit_team': {
189-
'id': self.user.dit_team.pk,
190-
},
191-
'was_policy_feedback_provided': False,
192-
}
193-
194-
api_client = self.create_api_client()
195-
response = api_client.post(url, request_data)
196-
assert response.status_code == status.HTTP_400_BAD_REQUEST
197-
assert response.json() == {
198-
'non_field_errors': ['Only one of contact and contacts should be provided.'],
199-
}
200-
201115
def test_error_returned_if_contacts_dont_belong_to_company(self):
202116
"""
203117
Test that an error is returned if the contacts don't belong to the specified company.
@@ -289,29 +203,6 @@ def test_date_validation(self):
289203
'Datetime has wrong format. Use one of these formats instead: YYYY-MM-DD.',
290204
]
291205

292-
def test_contact_copied_to_contacts(self):
293-
"""
294-
Test that the value provided in the contact field is copied to contacts when an
295-
interaction is updated.
296-
297-
TODO: remove once the contacts field has fully replaced the contact field.
298-
"""
299-
interaction = CompanyInteractionFactory(contacts=[])
300-
new_contact = ContactFactory(company=interaction.company)
301-
302-
url = reverse('api-v3:interaction:item', kwargs={'pk': interaction.pk})
303-
data = {
304-
'contact': {
305-
'id': new_contact.pk,
306-
},
307-
}
308-
response = self.api_client.patch(url, data=data)
309-
310-
assert response.status_code == status.HTTP_200_OK
311-
interaction.refresh_from_db()
312-
assert interaction.contact == new_contact
313-
assert list(interaction.contacts.all()) == [new_contact]
314-
315206
def test_contacts_copied_to_contact(self):
316207
"""
317208
Test that the value provided in the contact field is copied to contacts when an
@@ -335,31 +226,6 @@ def test_contacts_copied_to_contact(self):
335226
assert interaction.contact == new_contacts[0]
336227
assert set(interaction.contacts.all()) == set(new_contacts)
337228

338-
def test_providing_contact_and_contacts_returns_an_error(self):
339-
"""
340-
Test that if both contact and contacts are provided, an error is returned.
341-
342-
TODO: remove once the contacts field has fully replaced the contact field.
343-
"""
344-
interaction = CompanyInteractionFactory(contacts=[])
345-
new_contact = ContactFactory(company=interaction.company)
346-
347-
url = reverse('api-v3:interaction:item', kwargs={'pk': interaction.pk})
348-
data = {
349-
'contact': {
350-
'id': new_contact.pk,
351-
},
352-
'contacts': [{
353-
'id': new_contact.pk,
354-
}],
355-
}
356-
response = self.api_client.patch(url, data=data)
357-
358-
assert response.status_code == status.HTTP_400_BAD_REQUEST
359-
assert response.json() == {
360-
'non_field_errors': ['Only one of contact and contacts should be provided.'],
361-
}
362-
363229
@pytest.mark.parametrize(
364230
'request_data',
365231
(

0 commit comments

Comments
 (0)