Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pulling localized surveys #331

Merged
merged 27 commits into from
Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
25f4436
Partial tweaks for language tags
wasade May 25, 2021
48d132c
Merge branch 'i18n' of github.com:biocore/microsetta-private-api into…
wasade May 26, 2021
4ffff9b
update db patch for bristol chart
wasade May 26, 2021
631a905
Fix #301, provide height/weight to vioscreen
wasade May 26, 2021
05f0911
ci cursor is behaving different from local
wasade May 27, 2021
0be3e4e
...commit?
wasade May 27, 2021
e719e3e
Source IDs
wasade May 27, 2021
11e9110
Add a retry for 1005
wasade May 27, 2021
aa3fb49
Spanish needed to be reflecetd in another table
wasade May 28, 2021
6560743
..no need for pulling account id
wasade May 28, 2021
c3adafa
Fix #332
wasade May 28, 2021
c673d65
Fix #335
wasade May 28, 2021
2415f1a
Add section header translations
wasade May 28, 2021
d20697a
Source responses and headers properly
wasade May 28, 2021
bfca5c3
use static string from localization
wasade May 28, 2021
d9b1d34
Use the correct import...
wasade May 28, 2021
2815eda
Minor name change
wasade May 28, 2021
988d1c0
...the survey_response table should actually be used
wasade May 28, 2021
f9b1b09
move modification of 78 to 81
wasade May 28, 2021
7b44d21
Migrate to the correct table
wasade May 28, 2021
74f0727
Migrate 80 patch content as master already has an 80
wasade May 28, 2021
f687a3e
avoid an empty patch
wasade May 28, 2021
815bed2
missed one survey_response item
wasade May 28, 2021
2d83f95
beets and quinoa
wasade May 29, 2021
decf6d0
Handle null weight or height
wasade Jun 1, 2021
3389895
reduce diff
wasade Jun 1, 2021
d6c1a82
covid spanish translations
wasade Jun 2, 2021
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
10 changes: 7 additions & 3 deletions microsetta_private_api/api/_survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,19 @@ def read_survey_template(account_id, source_id, survey_template_id,
else:
raise ValueError("Vioscreen Template requires "
"vioscreen_ext_sample_id parameter.")
(birth_year, gender) = \
survey_template_repo.fetch_user_birth_year_gender(

(birth_year, gender, height, weight) = \
survey_template_repo.fetch_user_basic_physiology(
account_id, source_id)

url = vioscreen.gen_survey_url(
db_vioscreen_id,
language_tag,
survey_redirect_url,
birth_year=birth_year,
gender=gender
gender=gender,
height=height,
weight=weight
)
# TODO FIXME HACK: This field's contents are not specified!
info.survey_template_text = {
Expand Down
7 changes: 2 additions & 5 deletions microsetta_private_api/db/patches/0080.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
-- language is a reserved keyword in some variants of sql, (but not Postgres)
-- so we use preferred_language at the DB layer.
ALTER TABLE account ADD COLUMN preferred_language VARCHAR;
UPDATE account SET preferred_language='en_US';
ALTER TABLE account ALTER COLUMN preferred_language SET NOT NULL;
-- cannot have an empty patch
SELECT 1;
wasade marked this conversation as resolved.
Show resolved Hide resolved
1,710 changes: 1,710 additions & 0 deletions microsetta_private_api/db/patches/0081.sql

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions microsetta_private_api/model/vioscreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ def from_vioscreen(cls, sessions_data, users_data):
startDate, endDate, sessions_data['cultureCode'],
created, modified)

def __repr__(self):
args = ", ".join([f"{key}={str(value)}"
for key, value in self.__dict__.items()])
return f"VioscreenSession({args})"


class VioscreenPercentEnergyComponent(ModelBase):
def __init__(self, code, description, short_description, units, amount):
Expand Down
130 changes: 108 additions & 22 deletions microsetta_private_api/repo/survey_template_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ def get_survey_template_link_info(survey_id):
def get_survey_template(self, survey_id, language_tag):
tag_to_col = {
localization.EN_US: "survey_question.american",
localization.EN_GB: "survey_question.british"
localization.EN_GB: "survey_question.british",
localization.ES_MX: "survey_question.spanish"
}

if language_tag not in tag_to_col:
Expand Down Expand Up @@ -167,7 +168,8 @@ def get_survey_template(self, survey_id, language_tag):
def _get_group_localized_text(self, group_id, language_tag):
tag_to_col = {
localization.EN_US: "american",
localization.EN_GB: "british"
localization.EN_GB: "british",
localization.ES_MX: "spanish"
}
with self._transaction.cursor() as cur:
cur.execute("SELECT " +
Expand All @@ -183,7 +185,8 @@ def _get_group_localized_text(self, group_id, language_tag):
def _get_question_valid_responses(self, survey_question_id, language_tag):
tag_to_col = {
localization.EN_US: "survey_response.american",
localization.EN_GB: "survey_response.british"
localization.EN_GB: "survey_response.british",
localization.ES_MX: "survey_response.spanish",
}

with self._transaction.cursor() as cur:
Expand Down Expand Up @@ -271,29 +274,112 @@ def get_vioscreen_id_if_exists(self, account_id, source_id,
else:
return rows[0][0]

def fetch_user_birth_year_gender(self, account_id, source_id):
"""Given an account ID,
returns a tuple of (birth_year->int|None and gender->str|None)"""
birth_year = None
gender = None
def fetch_user_basic_physiology(self, account_id, source_id):
"""Given an account and source ID, obtain basic physiology properties

Parameters
----------
account_id : str, UUID
The account UUID
source_id : str, UUID
The source UUID

Notes
-----
The original intention with this method was to provide basic host
detail to Viocare for the reports they produce. By default,
Viocare interprets height and weight as standard.

Returns
-------
tuple, (int or None, int or None, float or None, float or None)
The tuple contents are (birth year, gender, height, weight).
"""
UNSPECIFIED = 'Unspecified'

with self._transaction.cursor() as cur:
# question IDs: 107 = gender, 112 = birth year
cur.execute("""SELECT q.survey_question_id, q.response
# from survey_answers for non-free text fields
cur.execute("""SELECT question_shortname, q.response
FROM ag_login_surveys AS s
JOIN survey_answers AS q
ON s.survey_id = q.survey_id
WHERE survey_question_id IN (112, 107)
JOIN survey_question
USING (survey_question_id)
WHERE question_shortname IN (
'HEIGHT_UNITS',
'WEIGHT_UNITS',
'BIRTH_YEAR',
'GENDER')
AND s.ag_login_id = %s
and s.source_id = %s""",
(account_id, source_id))

results = {name: value for name, value in cur.fetchall()}
birth_year = results.get('BIRTH_YEAR')
gender = results.get('GENDER')
height_units = results.get('HEIGHT_UNITS')
weight_units = results.get('WEIGHT_UNITS')

# from survey_answers_other for height/weight
cur.execute("""SELECT question_shortname, q.response
FROM ag_login_surveys AS s
JOIN survey_answers_other AS q
ON s.survey_id = q.survey_id
JOIN survey_question
USING (survey_question_id)
WHERE question_shortname IN (
'HEIGHT_CM',
'WEIGHT_KG')
AND s.ag_login_id = %s
and s.source_id = %s""",
(account_id, source_id))
for row in cur:
if row[0] == 107:
gender = row[1]
if gender == 'Unspecified':
gender = None
elif row[0] == 112:
try:
birth_year = int(row[1])
except ValueError:
pass # for 'Unspecified', stays None
return (birth_year, gender)

results = {name: value for name, value in cur.fetchall()}
height = results.get('HEIGHT_CM')
weight = results.get('WEIGHT_KG')

# normalize the return values
if birth_year is not None and birth_year.isdigit():
birth_year = int(birth_year)
else:
birth_year = None

if gender is not None and gender == UNSPECIFIED:
gender = None

# This sucks.
if height == UNSPECIFIED or weight_units == UNSPECIFIED:
height = None
elif height is not None:
# all survey_answers_other responses are of the form
# '["foo"]' :/
height = height[2:-2]
wasade marked this conversation as resolved.
Show resolved Hide resolved
if height == "":
height = None
else:
height = int(height)
if height_units == 'centimeters':
# to inches
height = height / 2.54
else:
# should not occur but just in case
height = None

if weight == UNSPECIFIED or weight_units == UNSPECIFIED:
weight = None
elif weight is not None:
# all survey_answers_other responses are of the form
# '["foo"]' :/
weight = weight[2:-2]
if weight == "":
weight = None
else:
weight = int(weight)
if weight_units == 'kilograms':
# to pounds
weight = weight * 2.20462
else:
# should not occur but just in case
weight = None

return (birth_year, gender, height, weight)
wasade marked this conversation as resolved.
Show resolved Hide resolved
75 changes: 75 additions & 0 deletions microsetta_private_api/repo/tests/test_survey_template_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@

# test identifiers with a vio ID
TEST1_ACCOUNT_ID = "80c327ca-a5c7-4c7f-b64b-b219d9ff0b47"
TEST1_SOURCE_ID = None
TEST1_SAMPLE_ID = "125a7cc5-41ae-44ef-983c-6f1a5213f668"
TEST1_SURVEY_ID = None
TEST1_VIO_ID = "1c689634cea0d11b"


# not in registry
TEST2_ACCOUNT_ID = "735e1689-6976-4d96-9a33-7a19f06602bf"
TEST2_SOURCE_ID = None
TEST2_SAMPLE_ID = "7380bb81-7401-45bd-85a0-51001f5f5cf1"


Expand All @@ -32,8 +35,80 @@
(TEST2_SAMPLE_ID, ))
TEST2_SOURCE_ID = cur.fetchone()

cur.execute("""SELECT survey_id
FROM ag.ag_login_surveys
WHERE ag_login_id=%s
AND source_id=%s
AND vioscreen_status IS NULL""",
(TEST1_ACCOUNT_ID, TEST1_SOURCE_ID))
TEST1_SURVEY_ID = cur.fetchone()


class SurveyTemplateTests(unittest.TestCase):
def test_fetch_user_basic_physiology(self):
with Transaction() as t:
tr = SurveyTemplateRepo(t)

# year and gender already set for this survey
# weight and height are scrambled in the test
# database as they're remarked as free text
with t.cursor() as cur:
cur.execute("""UPDATE ag.survey_answers_other
SET response='["254"]'
WHERE survey_id=%s AND survey_question_id=%s""",
(TEST1_SURVEY_ID, 108)) # height_cm
cur.execute("""UPDATE ag.survey_answers_other
SET response='["100"]'
WHERE survey_id=%s AND survey_question_id=%s""",
(TEST1_SURVEY_ID, 113)) # weight_kg

tr = SurveyTemplateRepo(t)

obs = tr.fetch_user_basic_physiology(TEST1_ACCOUNT_ID,
TEST1_SOURCE_ID)
exp = (1973, 'Male', 100, 220.462)
self.assertEqual(obs, exp)

cur.execute("""UPDATE ag.survey_answers_other
SET response='["100"]'
WHERE survey_id=%s AND survey_question_id=%s""",
(TEST1_SURVEY_ID, 108)) # height_cm
cur.execute("""UPDATE ag.survey_answers
SET response='inches'
WHERE survey_id=%s AND survey_question_id=%s""",
(TEST1_SURVEY_ID, 109)) # height_units
cur.execute("""UPDATE ag.survey_answers
SET response='pounds'
WHERE survey_id=%s AND survey_question_id=%s""",
(TEST1_SURVEY_ID, 114)) # weight_units

obs = tr.fetch_user_basic_physiology(TEST1_ACCOUNT_ID,
TEST1_SOURCE_ID)
exp = (1973, 'Male', 100, 100)
self.assertEqual(obs, exp)

# equiv of Unspecified for height
cur.execute("""UPDATE ag.survey_answers_other
SET response='[""]'
WHERE survey_id=%s AND survey_question_id=%s""",
(TEST1_SURVEY_ID, 108)) # height_cm

obs = tr.fetch_user_basic_physiology(TEST1_ACCOUNT_ID,
TEST1_SOURCE_ID)
exp = (1973, 'Male', None, 100)
self.assertEqual(obs, exp)

# equiv of Unspecified for weight
cur.execute("""UPDATE ag.survey_answers_other
SET response='[""]'
WHERE survey_id=%s AND survey_question_id=%s""",
(TEST1_SURVEY_ID, 113)) # weight_kg

obs = tr.fetch_user_basic_physiology(TEST1_ACCOUNT_ID,
TEST1_SOURCE_ID)
exp = (1973, 'Male', None, None)
self.assertEqual(obs, exp)

def test_create_vioscreen_id_valid(self):
with Transaction() as t:
template_repo = SurveyTemplateRepo(t)
Expand Down
Loading