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

Create extended field values for processing/facility type #1616

Merged
merged 4 commits into from
Feb 3, 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 @@ -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']
Comment on lines +99 to +101
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we may want to do this in reverse as well since each facility type is also included as a processing type. Better to err on the side of having the facility show up when searching either field for a particular value.

    if (raw_data.get('facility_type') and
       raw_data.get('processing_type') is None):
        raw_data['processing_type'] = raw_data['facility_type']

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh good point. I'll switch this up.

# 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