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

Commit

Permalink
Merge pull request #1616 from open-apparel-registry/cpc/add-extended-…
Browse files Browse the repository at this point in the history
…field-types

Create extended field values for processing/facility type
  • Loading branch information
caseycesari committed Feb 3, 2022
2 parents 6034c54 + 99edd75 commit 81827fa
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- 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)
- Create extended field values for processing/facility type [#1616](https://github.com/open-apparel-registry/open-apparel-registry/pull/1616)

### Changed

Expand Down
5 changes: 5 additions & 0 deletions src/app/src/components/FacilityDetailSidebarItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ const FacilityDetailSidebarItem = ({
const hasAdditionalContent = !embed && !!additionalContent?.length;
const additionalContentCount = additionalContent?.length;

// Temporary, until these field types can be handled
if (label === 'Processing Type' || label === 'Facility Type') {
return null;
}

return (
<div className={classes.item}>
<ListItem
Expand Down
60 changes: 59 additions & 1 deletion src/django/api/extended_fields.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import re
from django.core import exceptions as core_exceptions
from api.models import Contributor, ExtendedField
from api.facility_type_processing_type import (
get_facility_and_processing_type,
ALL_PROCESSING_TYPES
)


def extract_range_value(value):
Expand Down Expand Up @@ -43,6 +47,32 @@ def create_extendedfield(field, field_value, item, contributor):
field_value = {
'raw_values': field_value,
}
elif (field == ExtendedField.FACILITY_TYPE or
field == ExtendedField.PROCESSING_TYPE):
values = field_value

if isinstance(field_value, str):
values = (field_value.split('|') if '|' in field_value
else [field_value])

deduped_values = list(dict.fromkeys(values))
results = []

for value in deduped_values:
result = get_facility_and_processing_type(value)
if result[0] is None:
raise ValueError(
f'No match found for {field}. Value must '
'be one of the following: '
f'{", ".join(list(ALL_PROCESSING_TYPES.keys()))}'
)
results.append(result)

field_value = {
'raw_values': field_value,
'matched_values': results,
}

ExtendedField.objects.create(
contributor=contributor,
facility_list_item=item,
Expand All @@ -54,13 +84,27 @@ def create_extendedfield(field, field_value, item, contributor):
RAW_DATA_FIELDS = (ExtendedField.NUMBER_OF_WORKERS,
ExtendedField.NATIVE_LANGUAGE_NAME,
ExtendedField.PARENT_COMPANY,
ExtendedField.PRODUCT_TYPE)
ExtendedField.PRODUCT_TYPE,
ExtendedField.FACILITY_TYPE,
ExtendedField.PROCESSING_TYPE)


def create_extendedfields_for_single_item(item, raw_data):
if item.id is None:
return False
contributor = item.source.contributor

# Add a facility_type extended field if the user only
# submitted a processing_type
if (raw_data.get('processing_type') and
raw_data.get('facility_type') is None):
raw_data['facility_type'] = raw_data['processing_type']
# Add a processing_type extended field if the user only
# submitted a facility_type
elif (raw_data.get('facility_type') and
raw_data.get('processing_type') is None):
raw_data['processing_type'] = raw_data['facility_type']

for field in RAW_DATA_FIELDS:
field_value = raw_data.get(field)
create_extendedfield(field, field_value, item, contributor)
Expand All @@ -70,11 +114,25 @@ def create_extendedfields_for_listitem(item, fields, values):
if item.id is None:
return False
contributor = item.source.contributor

for field in RAW_DATA_FIELDS:
if field in fields:
field_value = values[fields.index(field)]
create_extendedfield(field, field_value, item, contributor)

# Add a facility_type extended field if the user only
# submitted a processing_type
if (field == 'processing_type' and
'facility_type' not in fields):
create_extendedfield('facility_type', field_value, item,
contributor)
# Add a processing_type extended field if the user only
# submitted a facility_type
elif (field == 'facility_type' and
'processing_type' not in fields):
create_extendedfield('processing_type', field_value, item,
contributor)


def update_extendedfields_for_list_item(list_item):
for extended_field in ExtendedField.objects.filter(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 2.2.24 on 2022-01-31 16:35

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0078_enable_searchable_embed_fields'),
]

operations = [
migrations.AlterField(
model_name='extendedfield',
name='field_name',
field=models.CharField(choices=[('country', 'country'), ('name', 'name'), ('address', 'address'), ('number_of_workers', 'number_of_workers'), ('native_language_name', 'native_language_name'), ('facility_type', 'facility_type'), ('processing_type', 'processing_type'), ('product_type', 'product_type'), ('parent_company', 'parent_company'), ('facility_type', 'facility_type'), ('processing_type', 'processing_type')], help_text='The name of the field, chosen from a strict list.', max_length=200),
),
migrations.AlterField(
model_name='historicalextendedfield',
name='field_name',
field=models.CharField(choices=[('country', 'country'), ('name', 'name'), ('address', 'address'), ('number_of_workers', 'number_of_workers'), ('native_language_name', 'native_language_name'), ('facility_type', 'facility_type'), ('processing_type', 'processing_type'), ('product_type', 'product_type'), ('parent_company', 'parent_company'), ('facility_type', 'facility_type'), ('processing_type', 'processing_type')], help_text='The name of the field, chosen from a strict list.', max_length=200),
),
]
6 changes: 5 additions & 1 deletion src/django/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2260,6 +2260,8 @@ class ExtendedField(models.Model):
PROCESSING_TYPE = 'processing_type'
PRODUCT_TYPE = 'product_type'
PARENT_COMPANY = 'parent_company'
FACILITY_TYPE = 'facility_type'
PROCESSING_TYPE = 'processing_type'

FIELD_CHOICES = (
(COUNTRY, COUNTRY),
Expand All @@ -2270,7 +2272,9 @@ class ExtendedField(models.Model):
(FACILITY_TYPE, FACILITY_TYPE),
(PROCESSING_TYPE, PROCESSING_TYPE),
(PRODUCT_TYPE, PRODUCT_TYPE),
(PARENT_COMPANY, PARENT_COMPANY))
(PARENT_COMPANY, PARENT_COMPANY),
(FACILITY_TYPE, FACILITY_TYPE),
(PROCESSING_TYPE, PROCESSING_TYPE))

contributor = models.ForeignKey(
'Contributor',
Expand Down
77 changes: 77 additions & 0 deletions src/django/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -7654,3 +7654,80 @@ def test_max_count(self):
}), content_type='application/json')
self.assertEqual(1, ExtendedField.objects.all().count())
self.assertEqual(response.status_code, 400)


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

def test_single_processing_value(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",
'processing_type': ['cutting']
}), content_type='application/json')
self.assertEqual(2, ExtendedField.objects.all().count())
ef = ExtendedField.objects.first()
self.assertEqual(ExtendedField.FACILITY_TYPE, ef.field_name)
self.assertEqual(
{'matched_values': [
[
'PROCESSING_TYPE',
'EXACT',
'Final Product Assembly',
'Cutting'
]
], 'raw_values': ['cutting']}, ef.value)
ef = ExtendedField.objects.last()
self.assertEqual(ExtendedField.PROCESSING_TYPE, ef.field_name)
self.assertEqual(
{'matched_values': [
[
'PROCESSING_TYPE',
'EXACT',
'Final Product Assembly',
'Cutting'
]
], 'raw_values': ['cutting']}, ef.value)

def test_multiple_facility_values(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",
'facility_type': ['office hq', 'final product assembly']
}), content_type='application/json')
self.assertEqual(2, ExtendedField.objects.all().count())
ef = ExtendedField.objects.first()
self.assertEqual(ExtendedField.FACILITY_TYPE, ef.field_name)
self.assertEqual(
{'matched_values': [
[
'FACILITY_TYPE',
'EXACT',
'Office / HQ',
'Office / HQ'
],
[
'FACILITY_TYPE',
'EXACT',
'Final Product Assembly',
'Final Product Assembly'
]
], 'raw_values': ['office hq', 'final product assembly']},
ef.value)

def test_invalid_value(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",
'processing_type': 'sadfjhasdf'
}), content_type='application/json')
self.assertEqual(0, ExtendedField.objects.all().count())
self.assertEqual(response.status_code, 400)
13 changes: 10 additions & 3 deletions src/django/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1254,19 +1254,26 @@ def create(self, request):

try:
create_extendedfields_for_single_item(item, request.data)
except core_exceptions.ValidationError as e:
except (core_exceptions.ValidationError, ValueError) as e:
error_message = ''

if isinstance(e, ValueError):
error_message = str(e)
else:
error_message = e.message

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

Expand Down

0 comments on commit 81827fa

Please sign in to comment.