Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Create product type extended field #1605

Merged
merged 2 commits into from
Feb 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added

- Add facility/processing type taxonomy and look-up function [#1601](https://github.com/open-apparel-registry/open-apparel-registry/pull/1601)
- Create product type extended field [#1605](https://github.com/open-apparel-registry/open-apparel-registry/pull/1605)
- Index custom text [#1607](https://github.com/open-apparel-registry/open-apparel-registry/pull/1607)

### Changed
Expand Down
5 changes: 4 additions & 1 deletion src/app/src/components/FacilityDetailSidebarExtended.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ const detailsSidebarStyles = theme =>
const formatAttribution = (createdAt, contributor) =>
`${moment(createdAt).format('LL')} by ${contributor}`;

const formatIfList = value =>
Array.isArray(value) ? value.map(v => <li>{v}</li>) : value;

/* eslint-disable camelcase */
const formatExtendedField = ({
value,
Expand All @@ -93,7 +96,7 @@ const formatExtendedField = ({
id,
formatValue = v => v,
}) => ({
primary: formatValue(value),
primary: formatIfList(formatValue(value)),
secondary: formatAttribution(updated_at, contributor_name),
verified,
key: id,
Expand Down
2 changes: 1 addition & 1 deletion src/app/src/util/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ export const EXTENDED_FIELD_TYPES = [
{
label: 'Product Type',
fieldName: 'product_type',
formatValue: v => v,
formatValue: v => v.raw_values,
},
{
label: 'Processing Type',
Expand Down
21 changes: 20 additions & 1 deletion src/django/api/extended_fields.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
from django.core import exceptions as core_exceptions
from api.models import Contributor, ExtendedField


Expand All @@ -8,6 +9,9 @@ def extract_range_value(value):
return {"min": min(values, default=0), "max": max(values, default=0)}


MAX_PRODUCT_TYPE_COUNT = 50


def create_extendedfield(field, field_value, item, contributor):
if field_value is not None and field_value != "":
if field == ExtendedField.NUMBER_OF_WORKERS:
Expand All @@ -25,6 +29,20 @@ def create_extendedfield(field, field_value, item, contributor):
'raw_value': field_value,
'name': field_value
}
elif field == ExtendedField.PRODUCT_TYPE:
if isinstance(field_value, str):
field_value = field_value.split('|')
if not isinstance(field_value, list):
raise core_exceptions.ValidationError(
'Expected product_type to be a list or string '
f'but got {field_value}')
if len(field_value) > MAX_PRODUCT_TYPE_COUNT:
raise core_exceptions.ValidationError(
f'You may submit a maximum of {MAX_PRODUCT_TYPE_COUNT} '
f'product types, not {len(field_value)}')
field_value = {
'raw_values': field_value,
}
ExtendedField.objects.create(
contributor=contributor,
facility_list_item=item,
Expand All @@ -35,7 +53,8 @@ def create_extendedfield(field, field_value, item, contributor):

RAW_DATA_FIELDS = (ExtendedField.NUMBER_OF_WORKERS,
ExtendedField.NATIVE_LANGUAGE_NAME,
ExtendedField.PARENT_COMPANY)
ExtendedField.PARENT_COMPANY,
ExtendedField.PRODUCT_TYPE)


def create_extendedfields_for_single_item(item, raw_data):
Expand Down
97 changes: 77 additions & 20 deletions src/django/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
WET_ROLLER_PRINTING,
get_facility_and_processing_type
)
from api.extended_fields import MAX_PRODUCT_TYPE_COUNT


class FacilityListCreateTest(APITestCase):
Expand Down Expand Up @@ -4436,6 +4437,16 @@ def setUp(self):
self.list_item.facility = self.facility
self.list_item.save()

def join_group_and_login(self):
self.client.logout()
group = auth.models.Group.objects.get(
name=FeatureGroups.CAN_SUBMIT_FACILITY,
)
self.user.groups.set([group.id])
self.user.save()
self.client.login(email=self.user_email,
password=self.user_password)


class SearchByList(APITestCase):
def setUp(self):
Expand Down Expand Up @@ -5973,16 +5984,6 @@ def setUp(self):
'extra_1': 'Extra data'
}

def join_group_and_login(self):
self.client.logout()
group = auth.models.Group.objects.get(
name=FeatureGroups.CAN_SUBMIT_FACILITY,
)
self.user.groups.set([group.id])
self.user.save()
self.client.login(email=self.user_email,
password=self.user_password)

def test_unauthenticated_receives_401(self):
self.client.logout()
response = self.client.post(self.url)
Expand Down Expand Up @@ -7555,16 +7556,6 @@ def setUp(self):
super(ParentCompanyTestCase, self).setUp()
self.url = reverse('facility-list')

def join_group_and_login(self):
self.client.logout()
group = auth.models.Group.objects.get(
name=FeatureGroups.CAN_SUBMIT_FACILITY,
)
self.user.groups.set([group.id])
self.user.save()
self.client.login(email=self.user_email,
password=self.user_password)

def test_submit_parent_company_no_match(self):
self.join_group_and_login()
self.client.post(self.url, {
Expand Down Expand Up @@ -7597,3 +7588,69 @@ def test_submit_parent_company_fuzzy_match(self):
'contributor_name': self.contributor.name,
'contributor_id': self.contributor.id
}, ef.value)


class ProductTypeTestCase(FacilityAPITestCaseBase):
def setUp(self):
super(ProductTypeTestCase, self).setUp()
self.url = reverse('facility-list')

def test_array(self):
self.join_group_and_login()
self.client.post(self.url, json.dumps({
'country': "US",
'name': "Azavea",
'address': "990 Spring Garden St., Philadelphia PA 19123",
'product_type': ['a', 'b']
}), content_type='application/json')
self.assertEqual(1, ExtendedField.objects.all().count())
ef = ExtendedField.objects.first()
self.assertEqual(ExtendedField.PRODUCT_TYPE, ef.field_name)
self.assertEqual({
'raw_values': ['a', 'b']
}, ef.value)

def test_string(self):
self.join_group_and_login()
self.client.post(self.url, json.dumps({
'country': "US",
'name': "Azavea",
'address': "990 Spring Garden St., Philadelphia PA 19123",
'product_type': 'a|b'
}), content_type='application/json')
self.assertEqual(1, ExtendedField.objects.all().count())
ef = ExtendedField.objects.first()
self.assertEqual(ExtendedField.PRODUCT_TYPE, ef.field_name)
self.assertEqual({
'raw_values': ['a', 'b']
}, ef.value)

def test_list_validation(self):
self.join_group_and_login()
response = self.client.post(self.url, json.dumps({
'country': "US",
'name': "Azavea",
'address': "990 Spring Garden St., Philadelphia PA 19123",
'product_type': {}
}), content_type='application/json')
self.assertEqual(0, ExtendedField.objects.all().count())
self.assertEqual(response.status_code, 400)

def test_max_count(self):
self.join_group_and_login()
response = self.client.post(self.url, json.dumps({
'country': "US",
'name': "Azavea",
'address': "990 Spring Garden St., Philadelphia PA 19123",
'product_type': [str(a) for a in range(MAX_PRODUCT_TYPE_COUNT)]
}), content_type='application/json')
self.assertEqual(1, ExtendedField.objects.all().count())

response = self.client.post(self.url, json.dumps({
'country': "US",
'name': "Azavea",
'address': "990 Spring Garden St., Philadelphia PA 19123",
'product_type': [str(a) for a in range(MAX_PRODUCT_TYPE_COUNT + 1)]
}), content_type='application/json')
self.assertEqual(1, ExtendedField.objects.all().count())
self.assertEqual(response.status_code, 400)
20 changes: 18 additions & 2 deletions src/django/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1244,8 +1244,6 @@ def create(self, request):
}]
)

create_extendedfields_for_single_item(item, request.data)

result = {
'matches': [],
'item_id': item.id,
Expand All @@ -1254,6 +1252,24 @@ def create(self, request):
'status': item.status,
}

try:
create_extendedfields_for_single_item(item, request.data)
except core_exceptions.ValidationError as e:
item.status = FacilityListItem.ERROR_PARSING
item.processing_results.append({
'action': ProcessingAction.PARSE,
'started_at': parse_started,
'error': True,
'message': e.message,
'trace': traceback.format_exc(),
'finished_at': str(datetime.utcnow()),
})
item.save()
result['status'] = item.status
result['message'] = e.message
return Response(result,
status=status.HTTP_400_BAD_REQUEST)

geocode_started = str(datetime.utcnow())
try:
geocode_result = geocode_address(address, country_code)
Expand Down